hc
2024-11-01 2f529f9b558ca1c1bd74be7437a84e4711743404
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/*
 * Copyright (C) 2001,2002,2003 Philippe Gerum <rpm@xenomai.org>.
 *
 * Xenomai is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation; either version 2 of the License,
 * or (at your option) any later version.
 *
 * Xenomai is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Xenomai; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 */
#ifndef _COBALT_KERNEL_SYNCH_H
#define _COBALT_KERNEL_SYNCH_H
 
#include <cobalt/kernel/list.h>
#include <cobalt/kernel/assert.h>
#include <cobalt/kernel/timer.h>
#include <cobalt/uapi/kernel/synch.h>
#include <cobalt/uapi/kernel/thread.h>
 
/**
 * @addtogroup cobalt_core_synch
 * @{
 */
#define XNSYNCH_CLAIMED  0x100    /* Claimed by other thread(s) (PI) */
#define XNSYNCH_CEILING  0x200    /* Actively boosting (PP) */
 
/* Spare flags usable by upper interfaces */
#define XNSYNCH_SPARE0  0x01000000
#define XNSYNCH_SPARE1  0x02000000
#define XNSYNCH_SPARE2  0x04000000
#define XNSYNCH_SPARE3  0x08000000
#define XNSYNCH_SPARE4  0x10000000
#define XNSYNCH_SPARE5  0x20000000
#define XNSYNCH_SPARE6  0x40000000
#define XNSYNCH_SPARE7  0x80000000
 
/* Statuses */
#define XNSYNCH_DONE    0    /* Resource available / operation complete */
#define XNSYNCH_WAIT    1    /* Calling thread blocked -- start rescheduling */
#define XNSYNCH_RESCHED 2    /* Force rescheduling */
 
struct xnthread;
struct xnsynch;
 
struct xnsynch {
   /** wait (weighted) prio in thread->boosters */
   int wprio;
   /** thread->boosters */
   struct list_head next;
   /**
    *  &variable holding the current priority ceiling value
    *  (xnsched_class_rt-based, [1..255], XNSYNCH_PP).
    */
   u32 *ceiling_ref;
   /** Status word */
   unsigned long status;
   /** Pending threads */
   struct list_head pendq;
   /** Thread which owns the resource */
   struct xnthread *owner;
    /** Pointer to fast lock word */
   atomic_t *fastlock;
   /* Cleanup handler */
   void (*cleanup)(struct xnsynch *synch);
};
 
#define XNSYNCH_WAITQUEUE_INITIALIZER(__name) {        \
       .status = XNSYNCH_PRIO,            \
       .wprio = -1,                \
       .pendq = LIST_HEAD_INIT((__name).pendq),    \
       .owner = NULL,                \
       .cleanup = NULL,            \
       .fastlock = NULL,            \
   }
 
#define DEFINE_XNWAITQ(__name)    \
   struct xnsynch __name = XNSYNCH_WAITQUEUE_INITIALIZER(__name)
 
static inline void xnsynch_set_status(struct xnsynch *synch, int bits)
{
   synch->status |= bits;
}
 
static inline void xnsynch_clear_status(struct xnsynch *synch, int bits)
{
   synch->status &= ~bits;
}
 
#define xnsynch_for_each_sleeper(__pos, __synch)        \
   list_for_each_entry(__pos, &(__synch)->pendq, plink)
 
#define xnsynch_for_each_sleeper_safe(__pos, __tmp, __synch)    \
   list_for_each_entry_safe(__pos, __tmp, &(__synch)->pendq, plink)
 
static inline int xnsynch_pended_p(struct xnsynch *synch)
{
   return !list_empty(&synch->pendq);
}
 
static inline struct xnthread *xnsynch_owner(struct xnsynch *synch)
{
   return synch->owner;
}
 
#define xnsynch_fastlock(synch)        ((synch)->fastlock)
#define xnsynch_fastlock_p(synch)    ((synch)->fastlock != NULL)
#define xnsynch_owner_check(synch, thread) \
   xnsynch_fast_owner_check((synch)->fastlock, thread->handle)
 
#ifdef CONFIG_XENO_OPT_DEBUG_MUTEX_RELAXED
 
void xnsynch_detect_relaxed_owner(struct xnsynch *synch,
                 struct xnthread *sleeper);
 
void xnsynch_detect_boosted_relax(struct xnthread *owner);
 
#else /* !CONFIG_XENO_OPT_DEBUG_MUTEX_RELAXED */
 
static inline void xnsynch_detect_relaxed_owner(struct xnsynch *synch,
                 struct xnthread *sleeper) { }
 
static inline void xnsynch_detect_boosted_relax(struct xnthread *owner) { }
 
#endif /* !CONFIG_XENO_OPT_DEBUG_MUTEX_RELAXED */
 
void xnsynch_init(struct xnsynch *synch, int flags,
         atomic_t *fastlock);
 
void xnsynch_init_protect(struct xnsynch *synch, int flags,
             atomic_t *fastlock, u32 *ceiling_ref);
 
int xnsynch_destroy(struct xnsynch *synch);
 
void xnsynch_commit_ceiling(struct xnthread *curr);
 
static inline void xnsynch_register_cleanup(struct xnsynch *synch,
                       void (*handler)(struct xnsynch *))
{
   synch->cleanup = handler;
}
 
int __must_check xnsynch_sleep_on(struct xnsynch *synch,
                 xnticks_t timeout,
                 xntmode_t timeout_mode);
 
struct xnthread *xnsynch_wakeup_one_sleeper(struct xnsynch *synch);
 
int xnsynch_wakeup_many_sleepers(struct xnsynch *synch, int nr);
 
void xnsynch_wakeup_this_sleeper(struct xnsynch *synch,
                struct xnthread *sleeper);
 
int __must_check xnsynch_acquire(struct xnsynch *synch,
                xnticks_t timeout,
                xntmode_t timeout_mode);
 
int __must_check xnsynch_try_acquire(struct xnsynch *synch);
 
bool xnsynch_release(struct xnsynch *synch, struct xnthread *thread);
 
struct xnthread *xnsynch_peek_pendq(struct xnsynch *synch);
 
int xnsynch_flush(struct xnsynch *synch, int reason);
 
void xnsynch_requeue_sleeper(struct xnthread *thread);
 
void xnsynch_forget_sleeper(struct xnthread *thread);
 
/** @} */
 
#endif /* !_COBALT_KERNEL_SYNCH_H_ */