revert between 56095 -> 55830 in arch
[AROS.git] / rom / exec / exec_locks.c
blob2083602ab89173e97cf4f0a1d6538dc4181b1b8f
1 /*
2 Copyright © 2017, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /*
7 Desc:
9 Exposes a Public resource on smp systems that allows user space code
10 to create (spin) locks, and exposes locking on exec Lists.
12 e.g. LDDemon uses this to lock access to the system lists
13 when scanning devices/libraries etc - since are not allowed
14 to directly call the kernel locking functions or access the exec locks.
16 Lang: english
19 #include <aros/config.h>
21 #if defined(__AROSEXEC_SMP__)
23 #define DEBUG 0
25 #include <aros/debug.h>
26 #include <proto/exec.h>
28 #include "exec_debug.h"
29 #include "exec_intern.h"
30 #include "exec_locks.h"
32 int ExecLock__InternObtainSystemLock(struct List *systemList, ULONG mode, ULONG flags)
34 spinlock_t *sysListLock = NULL;
35 D(char *name = "??");
37 if (systemList)
39 if (&SysBase->ResourceList == systemList) {
40 D(name="ResourceList");
41 sysListLock = &PrivExecBase(SysBase)->ResourceListSpinLock;
43 else if (&SysBase->DeviceList == systemList) {
44 D(name="DeviceList");
45 sysListLock = &PrivExecBase(SysBase)->DeviceListSpinLock;
47 else if (&SysBase->IntrList == systemList) {
48 D(name="IntrList");
49 sysListLock = &PrivExecBase(SysBase)->IntrListSpinLock;
51 else if (&SysBase->LibList == systemList) {
52 D(name="LibList");
53 sysListLock = &PrivExecBase(SysBase)->LibListSpinLock;
55 else if (&SysBase->PortList == systemList) {
56 D(name="PortList");
57 sysListLock = &PrivExecBase(SysBase)->PortListSpinLock;
59 else if (&SysBase->SemaphoreList == systemList) {
60 D(name="SemaphoreList");
61 sysListLock = &PrivExecBase(SysBase)->SemListSpinLock;
63 else if (&SysBase->MemList == systemList) {
64 D(name="MemList");
65 sysListLock = &PrivExecBase(SysBase)->MemListSpinLock;
67 else if (&SysBase->TaskReady == systemList) {
68 D(name="TaskReady");
69 sysListLock = &PrivExecBase(SysBase)->TaskReadySpinLock;
71 else if (&SysBase->TaskWait == systemList) {
72 D(name="TaskWait");
73 sysListLock = &PrivExecBase(SysBase)->TaskWaitSpinLock;
75 else if (&PrivExecBase(SysBase)->TaskRunning == systemList) {
76 D(name="TaskRunning");
77 sysListLock = &PrivExecBase(SysBase)->TaskRunningSpinLock;
79 else if (&PrivExecBase(SysBase)->TaskSpinning == systemList) {
80 D(name="TaskSpinning");
81 sysListLock = &PrivExecBase(SysBase)->TaskSpinningLock;
84 D(bug("[Exec:Lock] %s(), List='%s' (%p), mode=%s, flags=%d\n", __func__, name, systemList, mode == SPINLOCK_MODE_WRITE ? "write":"read", flags));
85 if (sysListLock)
87 if (flags && LOCKF_DISABLE)
88 Disable();
89 if (flags && LOCKF_FORBID)
90 Forbid();
92 EXEC_SPINLOCK_LOCK(sysListLock, NULL, mode);
94 return TRUE;
96 return FALSE;
99 void ExecLock__InternReleaseSystemLock(struct List *systemList, ULONG flags)
101 spinlock_t *sysListLock = NULL;
102 D(char *name = "??");
104 if (systemList)
106 if (&SysBase->ResourceList == systemList) {
107 D(name="ResourceList");
108 sysListLock = &PrivExecBase(SysBase)->ResourceListSpinLock;
110 else if (&SysBase->DeviceList == systemList) {
111 D(name="DeviceList");
112 sysListLock = &PrivExecBase(SysBase)->DeviceListSpinLock;
114 else if (&SysBase->IntrList == systemList) {
115 D(name="IntrList");
116 sysListLock = &PrivExecBase(SysBase)->IntrListSpinLock;
118 else if (&SysBase->LibList == systemList) {
119 D(name="LibList");
120 sysListLock = &PrivExecBase(SysBase)->LibListSpinLock;
122 else if (&SysBase->PortList == systemList) {
123 D(name="PortList");
124 sysListLock = &PrivExecBase(SysBase)->PortListSpinLock;
126 else if (&SysBase->SemaphoreList == systemList) {
127 D(name="SemaphoreList");
128 sysListLock = &PrivExecBase(SysBase)->SemListSpinLock;
130 else if (&SysBase->MemList == systemList) {
131 D(name="MemList");
132 sysListLock = &PrivExecBase(SysBase)->MemListSpinLock;
134 else if (&SysBase->TaskReady == systemList) {
135 D(name="TaskReady");
136 sysListLock = &PrivExecBase(SysBase)->TaskReadySpinLock;
138 else if (&SysBase->TaskWait == systemList) {
139 D(name="TaskWait");
140 sysListLock = &PrivExecBase(SysBase)->TaskWaitSpinLock;
142 else if (&PrivExecBase(SysBase)->TaskRunning == systemList) {
143 D(name="TaskRunning");
144 sysListLock = &PrivExecBase(SysBase)->TaskRunningSpinLock;
146 else if (&PrivExecBase(SysBase)->TaskSpinning == systemList) {
147 D(name="TaskSpinning");
148 sysListLock = &PrivExecBase(SysBase)->TaskSpinningLock;
151 D(bug("[Exec:Lock] %s(), list='%s' (%p), flags=%d\n", __func__, name, systemList, flags));
152 if (sysListLock)
154 EXEC_SPINLOCK_UNLOCK(sysListLock);
156 if (flags & LOCKF_FORBID)
157 Permit();
158 if (flags & LOCKF_DISABLE)
159 Enable();
163 /* Locking mechanism for userspace */
164 void * ExecLock__AllocLock()
166 spinlock_t *publicLock;
168 D(bug("[Exec:Lock] %s()\n", __func__));
170 if ((publicLock = (spinlock_t *)AllocMem(sizeof(spinlock_t), MEMF_ANY | MEMF_CLEAR)) != NULL)
172 EXEC_SPINLOCK_INIT(publicLock);
174 return publicLock;
177 int ExecLock__ObtainLock(void * lock, ULONG mode, ULONG flags)
179 D(bug("[Exec:Lock] %s()\n", __func__));
181 if (lock)
183 if (flags && LOCKF_DISABLE)
184 Disable();
185 if (flags && LOCKF_FORBID)
186 Forbid();
188 EXEC_SPINLOCK_LOCK(lock, NULL, mode);
189 return TRUE;
191 return FALSE;
194 void ExecLock__ReleaseLock(void *lock, ULONG flags)
196 D(bug("[Exec:Lock] %s()\n", __func__));
198 if (lock)
200 EXEC_SPINLOCK_UNLOCK(lock);
202 if (flags & LOCKF_FORBID)
203 Permit();
204 if (flags & LOCKF_DISABLE)
205 Enable();
209 void ExecLock__FreeLock(void *lock)
211 D(bug("[Exec:Lock] %s()\n", __func__));
213 if (lock)
215 FreeMem(lock, sizeof(spinlock_t));
219 AROS_LH3 (int, ObtainSystemLock,
220 AROS_LHA(struct List *, systemList, A0),
221 AROS_LHA(ULONG, mode, D0),
222 AROS_LHA(ULONG, flags, D1),
223 struct ExecLockBase *, ExecLockBase, 1, ExecLock
226 AROS_LIBFUNC_INIT
228 D(bug("[Exec:Lock] %s()\n", __func__));
230 return ExecLock__InternObtainSystemLock(systemList, mode, flags);
232 AROS_LIBFUNC_EXIT
235 AROS_LH2 (void, ReleaseSystemLock,
236 AROS_LHA(struct List *, systemList, A0),
237 AROS_LHA(ULONG, flags, D1),
238 struct ExecLockBase *, ExecLockBase, 2, ExecLock
241 AROS_LIBFUNC_INIT
243 D(bug("[Exec:Lock] %s()\n", __func__));
245 ExecLock__InternReleaseSystemLock(systemList, flags);
247 AROS_LIBFUNC_EXIT
250 AROS_LH0 (APTR, AllocLock,
251 struct ExecLockBase *, ExecLockBase, 3, ExecLock
254 AROS_LIBFUNC_INIT
256 D(bug("[Exec:Lock] %s()\n", __func__));
258 return ExecLock__AllocLock();
260 AROS_LIBFUNC_EXIT
263 AROS_LH1 (void, FreeLock,
264 AROS_LHA(APTR, lock, A0),
265 struct ExecLockBase *, ExecLockBase, 4, ExecLock
268 AROS_LIBFUNC_INIT
270 D(bug("[Exec:Lock] %s()\n", __func__));
272 ExecLock__FreeLock(lock);
274 AROS_LIBFUNC_EXIT
277 AROS_LH3 (int, ObtainLock,
278 AROS_LHA(APTR, lock, A0),
279 AROS_LHA(ULONG, mode, D0),
280 AROS_LHA(ULONG, flags, D1),
281 struct ExecLockBase *, ExecLockBase, 5, ExecLock
284 AROS_LIBFUNC_INIT
286 D(bug("[Exec:Lock] %s()\n", __func__));
288 return ExecLock__ObtainLock(lock, mode, flags);
290 AROS_LIBFUNC_EXIT
293 AROS_LH2 (void, ReleaseLock,
294 AROS_LHA(APTR, lock, A0),
295 AROS_LHA(ULONG, flags, D1),
296 struct ExecLockBase *, ExecLockBase, 6, ExecLock
299 AROS_LIBFUNC_INIT
301 D(bug("[Exec:Lock] %s()\n", __func__));
303 ExecLock__ReleaseLock(lock, flags);
305 AROS_LIBFUNC_EXIT
308 const APTR ExecLock__FuncTable[]=
310 &AROS_SLIB_ENTRY(ObtainSystemLock,ExecLock,1),
311 &AROS_SLIB_ENTRY(ReleaseSystemLock,ExecLock,2),
312 &AROS_SLIB_ENTRY(AllocLock,ExecLock,3),
313 &AROS_SLIB_ENTRY(FreeLock,ExecLock,4),
314 &AROS_SLIB_ENTRY(ObtainLock,ExecLock,5),
315 &AROS_SLIB_ENTRY(ReleaseLock,ExecLock,6),
316 (void *)-1
320 APTR ExecLock__PrepareBase(struct MemHeader *mh)
322 APTR ExecLockResBase;
323 struct ExecLockBase *ExecLockBase;
325 D(bug("[Exec:Lock] %s()\n", __func__));
327 ExecLockResBase = Allocate(mh, sizeof(struct ExecLockBase) + sizeof(ExecLock__FuncTable));
328 ExecLockBase = (struct ExecLockBase *)((IPTR)ExecLockResBase + sizeof(ExecLock__FuncTable));
330 MakeFunctions(ExecLockBase, ExecLock__FuncTable, NULL);
332 ExecLockBase->el_Node.ln_Name = "execlock.resource";
333 ExecLockBase->el_Node.ln_Type = NT_RESOURCE;
334 ExecLockBase->ObtainSystemLock = ExecLock__InternObtainSystemLock;
335 ExecLockBase->ReleaseSystemLock = ExecLock__InternReleaseSystemLock;
336 ExecLockBase->AllocLock = ExecLock__AllocLock;
337 ExecLockBase->FreeLock = ExecLock__FreeLock;
338 ExecLockBase->ObtainLock = ExecLock__ObtainLock;
339 ExecLockBase->ReleaseLock = ExecLock__ReleaseLock;
341 AddResource(ExecLockBase);
343 return ExecLockBase;
346 #endif