3 * Copyright 2007 Free Software Foundation, Inc.
5 * This file is part of GNU Radio
7 * GNU Radio is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
12 * GNU Radio is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include <gcell/gc_jd_stack.h>
23 #include <gcell/memory_barrier.h>
26 * begin extract from ppu_intrinics.h
27 * FIXME handle this a different way
30 #if !defined(__PPU__) && !defined(__ppc__) && !defined(__ppc64__)
32 #error ppu_intrinsics.h included on wrong platform/compiler
35 #define __lwarx(base) __extension__ \
36 ({unsigned int result; \
37 typedef struct {char a[4];} wordsize; \
38 wordsize *ptrp = (wordsize*)(base); \
39 __asm__ volatile ("lwarx %0,%y1" \
45 #define __ldarx(base) __extension__ \
46 ({unsigned long long result; \
47 typedef struct {char a[8];} doublewordsize; \
48 doublewordsize *ptrp = (doublewordsize*)(base); \
49 __asm__ volatile ("ldarx %0,%y1" \
53 #endif /* __powerpc64__ */
55 #define __stwcx(base, value) __extension__ \
56 ({unsigned int result; \
57 typedef struct {char a[4];} wordsize; \
58 wordsize *ptrp = (wordsize*)(base); \
59 __asm__ volatile ("stwcx. %2,%y1\n" \
64 ((result & 0x20000000) >> 29); })
68 #define __stdcx(base, value) __extension__ \
69 ({unsigned long long result; \
70 typedef struct {char a[8];} doublewordsize; \
71 doublewordsize *ptrp = (doublewordsize*)(base); \
72 __asm__ volatile ("stdcx. %2,%y1\n" \
77 ((result & 0x20000000) >> 29); })
78 #endif /* __powerpc64__ */
82 * --- end extract from ppu_intrinics.h --
87 gc_jd_stack_init(gc_jd_stack_t *stack)
93 #ifdef __powerpc64__ // 64-bit mode
96 gc_jd_stack_push(gc_jd_stack_t *stack, gc_job_desc_t *item)
99 gc_eaddr_t item_ea = ptr_to_ea(item);
103 top = __ldarx(&stack->top);
104 item->sys.next = top;
105 smp_wmb(); // order store of item->next before store of stack->top
106 done = __stdcx(&stack->top, item_ea);
107 } while (unlikely(done == 0));
111 gc_jd_stack_pop(gc_jd_stack_t *stack)
118 s = __ldarx(&stack->top);
119 if (s == 0) /* stack's empty */
121 t = ((gc_job_desc_t *) ea_to_ptr(s))->sys.next;
122 done = __stdcx(&stack->top, t);
123 } while (unlikely(done == 0));
131 * In 32-bit mode, gc_eaddr's will have the top 32-bits zero.
132 * The ldarx/stdcx instructions aren't available in 32-bit mode,
133 * thus we use lwarx/stwcx on the low 32-bits of the 64-bit addresses.
134 * Since we're big-endian, the low 32-bits are at word offset 1.
137 gc_jd_stack_push(gc_jd_stack_t *stack, gc_job_desc_t *item)
143 top = __lwarx((int32_t *)(&stack->top) + 1);
144 item->sys.next = top;
145 smp_wmb(); // order store of item->sys.next before store of stack->top
146 done = __stwcx((int32_t *)(&stack->top) + 1, item);
147 } while (unlikely(done == 0));
151 gc_jd_stack_pop(gc_jd_stack_t *stack)
158 s = __lwarx((int32_t *)(&stack->top) + 1);
159 if (s == 0) /* stack's empty */
161 t = ((gc_job_desc_t *) ea_to_ptr(s))->sys.next;
162 done = __stwcx((int32_t *)(&stack->top) + 1, (uint32_t) t);
163 } while (unlikely(done == 0));