X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=gcell%2Flib%2Fruntime%2Fgc_jd_stack.c;fp=gcell%2Flib%2Fruntime%2Fgc_jd_stack.c;h=4d865acf062065c28ac93eba91ef2444ea921091;hb=ea29b08aeb54227e6628f655ccfdb96fe4d8c378;hp=0000000000000000000000000000000000000000;hpb=09a1e803a9e6587c78d20cdf16891e5295874668;p=debian%2Fgnuradio diff --git a/gcell/lib/runtime/gc_jd_stack.c b/gcell/lib/runtime/gc_jd_stack.c new file mode 100644 index 00000000..4d865acf --- /dev/null +++ b/gcell/lib/runtime/gc_jd_stack.c @@ -0,0 +1,168 @@ +/* -*- c -*- */ +/* + * Copyright 2007 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +/* + * begin extract from ppu_intrinics.h + * FIXME handle this a different way + */ + +#if !defined(__PPU__) && !defined(__ppc__) && !defined(__ppc64__) + && !defined(__GNUC__) + #error ppu_intrinsics.h included on wrong platform/compiler +#endif + +#define __lwarx(base) __extension__ \ + ({unsigned int result; \ + typedef struct {char a[4];} wordsize; \ + wordsize *ptrp = (wordsize*)(base); \ + __asm__ volatile ("lwarx %0,%y1" \ + : "=r" (result) \ + : "Z" (*ptrp)); \ + result; }) + +#ifdef __powerpc64__ +#define __ldarx(base) __extension__ \ + ({unsigned long long result; \ + typedef struct {char a[8];} doublewordsize; \ + doublewordsize *ptrp = (doublewordsize*)(base); \ + __asm__ volatile ("ldarx %0,%y1" \ + : "=r" (result) \ + : "Z" (*ptrp)); \ + result; }) +#endif /* __powerpc64__ */ + +#define __stwcx(base, value) __extension__ \ + ({unsigned int result; \ + typedef struct {char a[4];} wordsize; \ + wordsize *ptrp = (wordsize*)(base); \ + __asm__ volatile ("stwcx. %2,%y1\n" \ + "\tmfocrf %0,0x80" \ + : "=r" (result), \ + "=Z" (*ptrp) \ + : "r" (value)); \ + ((result & 0x20000000) >> 29); }) + + +#ifdef __powerpc64__ +#define __stdcx(base, value) __extension__ \ + ({unsigned long long result; \ + typedef struct {char a[8];} doublewordsize; \ + doublewordsize *ptrp = (doublewordsize*)(base); \ + __asm__ volatile ("stdcx. %2,%y1\n" \ + "\tmfocrf %0,0x80" \ + : "=r" (result), \ + "=Z" (*ptrp) \ + : "r" (value)); \ + ((result & 0x20000000) >> 29); }) +#endif /* __powerpc64__ */ + + +/* + * --- end extract from ppu_intrinics.h -- + */ + + +void +gc_jd_stack_init(gc_jd_stack_t *stack) +{ + stack->top = 0; +} + + +#ifdef __powerpc64__ // 64-bit mode + +void +gc_jd_stack_push(gc_jd_stack_t *stack, gc_job_desc_t *item) +{ + gc_eaddr_t top; + gc_eaddr_t item_ea = ptr_to_ea(item); + unsigned int done; + + do { + top = __ldarx(&stack->top); + item->sys.next = top; + smp_wmb(); // order store of item->next before store of stack->top + done = __stdcx(&stack->top, item_ea); + } while (unlikely(done == 0)); +} + +gc_job_desc_t * +gc_jd_stack_pop(gc_jd_stack_t *stack) +{ + gc_eaddr_t s; + gc_eaddr_t t; + unsigned int done; + + do { + s = __ldarx(&stack->top); + if (s == 0) /* stack's empty */ + return 0; + t = ((gc_job_desc_t *) ea_to_ptr(s))->sys.next; + done = __stdcx(&stack->top, t); + } while (unlikely(done == 0)); + + return ea_to_ptr(s); +} + +#else // 32-bit mode + +/* + * In 32-bit mode, gc_eaddr's will have the top 32-bits zero. + * The ldarx/stdcx instructions aren't available in 32-bit mode, + * thus we use lwarx/stwcx on the low 32-bits of the 64-bit addresses. + * Since we're big-endian, the low 32-bits are at word offset 1. + */ +void +gc_jd_stack_push(gc_jd_stack_t *stack, gc_job_desc_t *item) +{ + gc_eaddr_t top; + unsigned int done; + + do { + top = __lwarx((int32_t *)(&stack->top) + 1); + item->sys.next = top; + smp_wmb(); // order store of item->sys.next before store of stack->top + done = __stwcx((int32_t *)(&stack->top) + 1, item); + } while (unlikely(done == 0)); +} + +gc_job_desc_t * +gc_jd_stack_pop(gc_jd_stack_t *stack) +{ + gc_eaddr_t s; + gc_eaddr_t t; + unsigned int done; + + do { + s = __lwarx((int32_t *)(&stack->top) + 1); + if (s == 0) /* stack's empty */ + return 0; + t = ((gc_job_desc_t *) ea_to_ptr(s))->sys.next; + done = __stwcx((int32_t *)(&stack->top) + 1, (uint32_t) t); + } while (unlikely(done == 0)); + + return ea_to_ptr(s); +} + +#endif