2 Copyright © 2017, The AROS Development Team. All rights reserved.
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.
19 #include <aros/config.h>
21 #if defined(__AROSEXEC_SMP__)
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
;
39 if (&SysBase
->ResourceList
== systemList
) {
40 D(name
="ResourceList");
41 sysListLock
= &PrivExecBase(SysBase
)->ResourceListSpinLock
;
43 else if (&SysBase
->DeviceList
== systemList
) {
45 sysListLock
= &PrivExecBase(SysBase
)->DeviceListSpinLock
;
47 else if (&SysBase
->IntrList
== systemList
) {
49 sysListLock
= &PrivExecBase(SysBase
)->IntrListSpinLock
;
51 else if (&SysBase
->LibList
== systemList
) {
53 sysListLock
= &PrivExecBase(SysBase
)->LibListSpinLock
;
55 else if (&SysBase
->PortList
== systemList
) {
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
) {
65 sysListLock
= &PrivExecBase(SysBase
)->MemListSpinLock
;
67 else if (&SysBase
->TaskReady
== systemList
) {
69 sysListLock
= &PrivExecBase(SysBase
)->TaskReadySpinLock
;
71 else if (&SysBase
->TaskWait
== systemList
) {
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
));
87 if (flags
&& LOCKF_DISABLE
)
89 if (flags
&& LOCKF_FORBID
)
92 EXEC_SPINLOCK_LOCK(sysListLock
, NULL
, mode
);
99 void ExecLock__InternReleaseSystemLock(struct List
*systemList
, ULONG flags
)
101 spinlock_t
*sysListLock
= NULL
;
102 D(char *name
= "??");
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
) {
116 sysListLock
= &PrivExecBase(SysBase
)->IntrListSpinLock
;
118 else if (&SysBase
->LibList
== systemList
) {
120 sysListLock
= &PrivExecBase(SysBase
)->LibListSpinLock
;
122 else if (&SysBase
->PortList
== systemList
) {
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
) {
132 sysListLock
= &PrivExecBase(SysBase
)->MemListSpinLock
;
134 else if (&SysBase
->TaskReady
== systemList
) {
136 sysListLock
= &PrivExecBase(SysBase
)->TaskReadySpinLock
;
138 else if (&SysBase
->TaskWait
== systemList
) {
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
));
154 EXEC_SPINLOCK_UNLOCK(sysListLock
);
156 if (flags
& LOCKF_FORBID
)
158 if (flags
& LOCKF_DISABLE
)
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
);
177 int ExecLock__ObtainLock(void * lock
, ULONG mode
, ULONG flags
)
179 D(bug("[Exec:Lock] %s()\n", __func__
));
183 if (flags
&& LOCKF_DISABLE
)
185 if (flags
&& LOCKF_FORBID
)
188 EXEC_SPINLOCK_LOCK(lock
, NULL
, mode
);
194 void ExecLock__ReleaseLock(void *lock
, ULONG flags
)
196 D(bug("[Exec:Lock] %s()\n", __func__
));
200 EXEC_SPINLOCK_UNLOCK(lock
);
202 if (flags
& LOCKF_FORBID
)
204 if (flags
& LOCKF_DISABLE
)
209 void ExecLock__FreeLock(void *lock
)
211 D(bug("[Exec:Lock] %s()\n", __func__
));
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
228 D(bug("[Exec:Lock] %s()\n", __func__
));
230 return ExecLock__InternObtainSystemLock(systemList
, mode
, flags
);
235 AROS_LH2 (void, ReleaseSystemLock
,
236 AROS_LHA(struct List
*, systemList
, A0
),
237 AROS_LHA(ULONG
, flags
, D1
),
238 struct ExecLockBase
*, ExecLockBase
, 2, ExecLock
243 D(bug("[Exec:Lock] %s()\n", __func__
));
245 ExecLock__InternReleaseSystemLock(systemList
, flags
);
250 AROS_LH0 (APTR
, AllocLock
,
251 struct ExecLockBase
*, ExecLockBase
, 3, ExecLock
256 D(bug("[Exec:Lock] %s()\n", __func__
));
258 return ExecLock__AllocLock();
263 AROS_LH1 (void, FreeLock
,
264 AROS_LHA(APTR
, lock
, A0
),
265 struct ExecLockBase
*, ExecLockBase
, 4, ExecLock
270 D(bug("[Exec:Lock] %s()\n", __func__
));
272 ExecLock__FreeLock(lock
);
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
286 D(bug("[Exec:Lock] %s()\n", __func__
));
288 return ExecLock__ObtainLock(lock
, mode
, flags
);
293 AROS_LH2 (void, ReleaseLock
,
294 AROS_LHA(APTR
, lock
, A0
),
295 AROS_LHA(ULONG
, flags
, D1
),
296 struct ExecLockBase
*, ExecLockBase
, 6, ExecLock
301 D(bug("[Exec:Lock] %s()\n", __func__
));
303 ExecLock__ReleaseLock(lock
, flags
);
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),
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
);