Merge origin/netpush (networking code) (XCC)
[akaros.git] / kern / include / ros / ucq.h
1 /* Copyright (c) 2011 The Regents of the University of California
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * Unbounded concurrent queues.  Linked buffers/arrays of elements, in page
6  * size chunks.  The pages/buffers are linked together by an info struct at the
7  * beginning of the page.  Producers and consumers sync on the idxes when
8  * operating in a page, and page swaps are synced via the proc* for the kernel
9  * and via the ucq's u_lock for the user. 
10  *
11  * There's a bunch of details and issues discussed in the Documentation.
12  *
13  * This header contains the stuff that the kernel and userspace need to agree
14  * on.  Each side of the implementation will have their own .c and .h files.
15  * The kernel's implementation is in kern/src/ucq.c, and the user's is in
16  * user/parlib/ucq.c. */
17
18 #ifndef ROS_INC_UCQ_H
19 #define ROS_INC_UCQ_H
20
21 #include <ros/common.h>
22 #include <ros/atomic.h>
23 #include <ros/arch/mmu.h>
24 #include <arch/arch.h>                  /* both user and kernel have arch/arch.h */
25 /* #include <ros/event.h> included below */
26
27 /* The main UCQ structure, contains indexes and start points (for the indexes),
28  * etc. */
29 struct ucq {
30         atomic_t                                        prod_idx;               /* both pg and slot nr */
31         bool                                            prod_overflow;  /* flag to prevent wraparound */
32         atomic_t                                        spare_pg;               /* mmaped, unused page */
33         atomic_t                                        nr_extra_pgs;   /* nr pages mmaped */
34         atomic_t                                        cons_idx;               /* cons pg and slot nr */
35         bool                                            ucq_ready;              /* ucq is ready to be used */
36         /* Userspace lock for modifying the UCQ */
37         char                                            u_lock[2 * ARCH_CL_SIZE];       /* mcs_pdr_lock */
38 };
39
40 /* Struct at the beginning of every page/buffer, tracking consumers and
41  * pointing to the next one, so that the consumer can follow. */
42 struct ucq_page_header {
43         uintptr_t                                       cons_next_pg;   /* next page to consume */
44         atomic_t                                        nr_cons;                /* like an inverted refcnt */
45 };
46
47 /* Including here since event.h needs to know about struct ucq */
48 #include <ros/event.h>
49
50 struct msg_container {
51         struct event_msg                        ev_msg;
52         bool                                            ready;                  /* kernel has written */
53 };
54
55 struct ucq_page {
56         struct ucq_page_header          header;
57         struct msg_container            msgs[];
58 };
59
60 #define UCQ_WARN_THRESH                 1000                    /* nr pages befor warning */
61
62 #define NR_MSG_PER_PAGE ((PGSIZE - ROUNDUP(sizeof(struct ucq_page_header),     \
63                                            __alignof__(struct msg_container))) \
64                          / sizeof(struct msg_container))
65
66 /* A slot encodes both the page addr and the count within the page */
67 static bool slot_is_good(uintptr_t slot)
68 {
69         uintptr_t counter = PGOFF(slot);
70         uintptr_t pg_addr = PTE_ADDR(slot);
71         return ((counter < NR_MSG_PER_PAGE) && pg_addr) ? TRUE : FALSE;
72 }
73
74 /* Helper: converts a slot/index into a msg container.  The ucq_page is the
75  * PPN/PTE_ADDR of 'slot', and the specific slot *number* is the PGOFF.  Assumes
76  * the slot is good.  If it isn't, you're going to get random memory.
77  *
78  * Note that this doesn't actually read the memory, just computes an address. */
79 static inline struct msg_container *slot2msg(uintptr_t slot)
80 {
81         return &((struct ucq_page*)PTE_ADDR(slot))->msgs[PGOFF(slot)];
82 }
83
84 #endif /* ROS_INC_UCQ_H */