Fixes disable_kevent()
[akaros.git] / user / parlib / include / mcs.h
1 #ifndef _MCS_H
2 #define _MCS_H
3
4 #ifdef __cplusplus
5 extern "C" {
6 #endif
7
8 #include <vcore.h>
9 #include <arch/arch.h>
10
11 #define MCS_LOCK_INIT {0}
12
13 typedef struct mcs_lock_qnode
14 {
15         volatile struct mcs_lock_qnode* volatile next;
16         volatile int locked;
17 } mcs_lock_qnode_t;
18
19 typedef struct mcs_lock
20 {
21         mcs_lock_qnode_t* lock;
22 } mcs_lock_t;
23
24 typedef struct
25 {
26         volatile int myflags[2][LOG2_MAX_VCORES];
27         volatile int* partnerflags[2][LOG2_MAX_VCORES];
28         int parity;
29         int sense;
30         char pad[ARCH_CL_SIZE];
31 } mcs_dissem_flags_t;
32
33 typedef struct
34 {
35         size_t nprocs;
36         mcs_dissem_flags_t* allnodes;
37         size_t logp;
38 } mcs_barrier_t;
39
40 int mcs_barrier_init(mcs_barrier_t* b, size_t nprocs);
41 void mcs_barrier_wait(mcs_barrier_t* b, size_t vcoreid);
42
43 void mcs_lock_init(struct mcs_lock *lock);
44 /* Caller needs to alloc (and zero) their own qnode to spin on.  The memory
45  * should be on a cacheline that is 'per-thread'.  This could be on the stack,
46  * in a thread control block, etc. */
47 void mcs_lock_lock(struct mcs_lock *lock, struct mcs_lock_qnode *qnode);
48 void mcs_lock_unlock(struct mcs_lock *lock, struct mcs_lock_qnode *qnode);
49 /* If you lock the lock from vcore context, you must use these. */
50 void mcs_lock_notifsafe(struct mcs_lock *lock, struct mcs_lock_qnode *qnode);
51 void mcs_unlock_notifsafe(struct mcs_lock *lock, struct mcs_lock_qnode *qnode);
52
53 #ifdef __cplusplus
54 }
55 #endif
56
57 #endif