]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/plr/include/pthread_rep.h
update: sync
[l4.git] / l4 / pkg / plr / include / pthread_rep.h
1 #pragma once
2
3 #include <l4/util/atomic.h>
4
5 struct spinlock
6 {
7         unsigned int value;
8 };
9
10
11 typedef struct spinlock spinlock_t;
12
13
14 #define fence() asm volatile ("" ::: "memory");
15
16
17 inline static unsigned int
18 fas_uint(volatile unsigned int *lock, unsigned int val)
19 {
20         __asm__ __volatile__("xchgl %0, %1"
21              : "+m" (*lock), "+q" (val)
22              :
23              : "memory");
24         return val;
25 }
26
27
28 static inline void
29 stall(void)
30 {
31         asm volatile ("ud2" ::: "memory");
32 }
33
34
35 enum {
36         mutex_init_id   = 0,
37         mutex_lock_id   = 1,
38         mutex_unlock_id = 2,
39         pt_lock_id      = 3,
40         pt_unlock_id    = 4,
41         pt_max_wrappers = 5,
42
43         lock_entry_free = 0,
44         lock_unlocking  = 0xAAAAAAAA,
45         lock_unowned    = 0xFFFFFFFF,
46
47         NUM_TRAMPOLINES = 32,
48         TRAMPOLINE_SIZE = 32,
49         NUM_LOCKS       = 64,
50         LOCK_INFO_ADDR  = 0xA000,
51 };
52
53 typedef struct {
54   unsigned char trampolines[NUM_TRAMPOLINES * TRAMPOLINE_SIZE];
55   struct {
56           volatile l4_addr_t lockdesc;    // corresponding pthread_mutex_t ptr
57           volatile l4_addr_t owner;       // lock owner
58           volatile l4_addr_t owner_epoch; // lock holder's epoch
59           volatile l4_addr_t wait_count;  // count how many threads wait to acquire this lock
60           volatile l4_addr_t acq_count;   // count how many threads acquired this lock
61           volatile l4_addr_t wake_count;  // count how many threads should be unlocked
62           volatile spinlock_t lock;       // internal: lock for this row
63   } locks[NUM_LOCKS];
64   volatile l4_umword_t replica_count; // number of replicas running a.t.m.
65 } lock_info;
66
67 /* Compile-time assertion: lock_info must fit into a page) */
68 char __lock_info_size_valid[!!(sizeof(lock_info) <= L4_PAGESIZE)-1];
69
70 lock_info* get_lock_info(void);
71 lock_info* get_lock_info(void) {
72         return (lock_info*)LOCK_INFO_ADDR;
73 }
74
75
76 static inline void lock_li(volatile lock_info *li, unsigned idx)
77 {
78         volatile spinlock_t *lock = &li->locks[idx].lock;
79         while (fas_uint(&lock->value, 1) == 1) {
80                 stall();
81         }
82         fence();
83 }
84
85 static inline void unlock_li(volatile lock_info* li, unsigned idx)
86 {
87         fence();
88         li->locks[idx].lock.value = 0;
89 }
90
91
92 static char const *
93 __attribute__((used))
94 lockID_to_str(unsigned id)
95 {
96         switch(id) {
97                 case mutex_init_id:   return "mutex_init";
98                 case mutex_lock_id:   return "mutex_lock";
99                 case mutex_unlock_id: return "mutex_unlock";
100                 case pt_lock_id:      return "__pthread_lock";
101                 case pt_unlock_id:    return "__pthread_unlock";
102                 default: return "???";
103         }
104 }