aboutsummaryrefslogtreecommitdiff
path: root/include/kpl/object.h
blob: 751088d10265939ded1dad13f1e1c6e8ae485fba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/*
 * KPL specific objects
 */

#pragma once

// for atomic linked list queue
// size in bytes, index on the kpl_threads array
#define KPL_OBJECT_HEADER(STRUCT_NAME) \
    struct STRUCT_NAME *_Atomic queue_next; \
    int32_t object_size, thread_id

typedef struct _kpl_object {
    KPL_OBJECT_HEADER(_kpl_object);
} kpl_object; // all kpl objects allocated by the kpl memory allocator extend this header

/*
 * Atomic linked list queue any thread can add, only owner thread can remove
 */
typedef struct {
    kpl_object *_Atomic head, *tail; // head is modified with atomic exchange
    struct {
        kpl_object *_Atomic queue_next;
    } dummy; // head and tail are never null will always point to this
} kpl_object_queue;

/*
 * Only owner thread can call this
 */
inline void kpl_object_queue_init(kpl_object_queue *object_queue) {
    __atomic_store_n(&object_queue->dummy.queue_next, NULL, __ATOMIC_RELAXED);
    __atomic_store_n(&object_queue->head, &object_queue->dummy, __ATOMIC_RELAXED);
    object_queue->tail = (kpl_object*) &object_queue->dummy;
}

/*
 * Always succeeds, any thread can call this
 */
inline void kpl_object_queue_enqueue(kpl_object_queue *object_queue, void *object) {
    kpl_object *obj = object;
    __atomic_store_n(&obj->queue_next, NULL, __ATOMIC_RELAXED);
    kpl_object *head = __atomic_exchange_n(&object_queue->head, obj, __ATOMIC_SEQ_CST);
    __atomic_store_n(&head->queue_next, obj, __ATOMIC_RELEASE);
}

/*
 * Null for not found, only owner thread can call this
 */
void *kpl_object_queue_dequeue(kpl_object_queue *object_queue);

typedef void kpl_task_fn(kpl_task *task, kpl_env *env);

typedef struct _kpl_task {
    KPL_OBJECT_HEADER(_kpl_task);
    // TODO
} kpl_task;