| From 4bdd15e05f47164664d41602d35fd7aab504a7c6 Mon Sep 17 00:00:00 2001 |
| From: Stephen Barber <smbarber@chromium.org> |
| Date: Wed, 8 Apr 2020 16:11:31 -0700 |
| Subject: [PATCH] arm: replace co_swap_function array with inline asm |
| |
| Submitted upstream as https://github.com/canonical/libco/pull/13 |
| |
| --- |
| arm.c | 65 +++++++++++++++++++++++------------------------------------ |
| 1 file changed, 25 insertions(+), 40 deletions(-) |
| |
| diff --git a/arm.c b/arm.c |
| index 20c9531..7e9636b 100644 |
| --- a/arm.c |
| +++ b/arm.c |
| @@ -13,27 +13,24 @@ extern "C" { |
| |
| static thread_local unsigned long co_active_buffer[64]; |
| static thread_local cothread_t co_active_handle = 0; |
| -static void (*co_swap)(cothread_t, cothread_t) = 0; |
| +void co_swap(cothread_t, cothread_t); |
| |
| -#ifdef LIBCO_MPROTECT |
| - alignas(4096) |
| -#else |
| - section(text) |
| -#endif |
| -static const unsigned long co_swap_function[1024] = { |
| - 0xe8a16ff0, /* stmia r1!, {r4-r11,sp,lr} */ |
| - 0xe8b0aff0, /* ldmia r0!, {r4-r11,sp,pc} */ |
| - 0xe12fff1e, /* bx lr */ |
| -}; |
| +__asm__( |
| + ".text\n" |
| + ".align 4\n" |
| + ".type co_swap #function\n" |
| + ".arm\n" |
| + "co_swap:\n" |
| + "mov r3, sp\n" |
| + "stmia r1!, {r4-r11}\n" |
| + "stmia r1!, {r3, lr}\n" |
| + "ldmia r0!, {r4-r11}\n" |
| + "ldmia r0!, {r3, lr}\n" |
| + "mov sp, r3\n" |
| + "bx lr\n" |
| |
| -static void co_init() { |
| - #ifdef LIBCO_MPROTECT |
| - unsigned long addr = (unsigned long)co_swap_function; |
| - unsigned long base = addr - (addr % sysconf(_SC_PAGESIZE)); |
| - unsigned long size = (addr - base) + sizeof co_swap_function; |
| - mprotect((void*)base, size, PROT_READ | PROT_EXEC); |
| - #endif |
| -} |
| + ".size co_swap, .-co_swap\n" |
| +); |
| |
| cothread_t co_active() { |
| if(!co_active_handle) co_active_handle = &co_active_buffer; |
| @@ -42,14 +39,11 @@ cothread_t co_active() { |
| |
| cothread_t co_derive(void* memory, unsigned int size, void (*entrypoint)(void)) { |
| unsigned long* handle; |
| - if(!co_swap) { |
| - co_init(); |
| - co_swap = (void (*)(cothread_t, cothread_t))co_swap_function; |
| - } |
| if(!co_active_handle) co_active_handle = &co_active_buffer; |
| |
| if(handle = (unsigned long*)memory) { |
| - unsigned long* p = (unsigned long*)((unsigned char*)handle + size); |
| + unsigned int offset = (size & ~15); |
| + unsigned long* p = (unsigned long*)((unsigned char*)handle + offset); |
| handle[8] = (unsigned long)p; |
| handle[9] = (unsigned long)entrypoint; |
| } |
| @@ -58,22 +52,9 @@ cothread_t co_derive(void* memory, unsigned int size, void (*entrypoint)(void)) |
| } |
| |
| cothread_t co_create(unsigned int size, void (*entrypoint)(void)) { |
| - unsigned long* handle; |
| - if(!co_swap) { |
| - co_init(); |
| - co_swap = (void (*)(cothread_t, cothread_t))co_swap_function; |
| - } |
| - if(!co_active_handle) co_active_handle = &co_active_buffer; |
| - size += 256; |
| - size &= ~15; |
| - |
| - if(handle = (unsigned long*)malloc(size)) { |
| - unsigned long* p = (unsigned long*)((unsigned char*)handle + size); |
| - handle[8] = (unsigned long)p; |
| - handle[9] = (unsigned long)entrypoint; |
| - } |
| - |
| - return handle; |
| + void* memory = malloc(size); |
| + if(!memory) return (cothread_t)0; |
| + return co_derive(memory, size, entrypoint); |
| } |
| |
| void co_delete(cothread_t handle) { |
| @@ -85,6 +66,10 @@ void co_switch(cothread_t handle) { |
| co_swap(co_active_handle = handle, co_previous_handle); |
| } |
| |
| +int co_serializable() { |
| + return 1; |
| +} |
| + |
| #ifdef __cplusplus |
| } |
| #endif |
| -- |
| 2.26.0.292.g33ef6b2f38-goog |
| |