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