commit the wip init of execlock resources public api.
[AROS.git] / rom / exec / exec_locks.c
blobfca2bc399d9cc0b7d0c4eec5bc9a81cf2a765a9c
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 1
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;
64 D(bug("[Exec:Lock] %s(), List='%s' (%p), mode=%s, flags=%d\n", __func__, name, systemList, mode == SPINLOCK_MODE_WRITE ? "write":"read", flags));
65 if (sysListLock)
67 if (flags && LOCKF_DISABLE)
68 Disable();
69 if (flags && LOCKF_FORBID)
70 Forbid();
72 EXEC_SPINLOCK_LOCK(sysListLock, NULL, mode);
74 return TRUE;
76 return FALSE;
79 void ExecLock__InternReleaseSystemLock(struct List *systemList, ULONG flags)
81 spinlock_t *sysListLock = NULL;
82 D(char *name = "??");
84 if (systemList)
86 if (&SysBase->ResourceList == systemList) {
87 D(name="ResourceList");
88 sysListLock = &PrivExecBase(SysBase)->ResourceListSpinLock;
90 else if (&SysBase->DeviceList == systemList) {
91 D(name="DeviceList");
92 sysListLock = &PrivExecBase(SysBase)->DeviceListSpinLock;
94 else if (&SysBase->IntrList == systemList) {
95 D(name="IntrList");
96 sysListLock = &PrivExecBase(SysBase)->IntrListSpinLock;
98 else if (&SysBase->LibList == systemList) {
99 D(name="LibList");
100 sysListLock = &PrivExecBase(SysBase)->LibListSpinLock;
102 else if (&SysBase->PortList == systemList) {
103 D(name="PortList");
104 sysListLock = &PrivExecBase(SysBase)->PortListSpinLock;
106 else if (&SysBase->SemaphoreList == systemList) {
107 D(name="SemaphoreList");
108 sysListLock = &PrivExecBase(SysBase)->SemListSpinLock;
111 D(bug("[Exec:Lock] %s(), list='%s' (%p), flags=%d\n", __func__, name, systemList, flags));
112 if (sysListLock)
114 EXEC_SPINLOCK_UNLOCK(sysListLock);
116 if (flags & LOCKF_FORBID)
117 Permit();
118 if (flags & LOCKF_DISABLE)
119 Enable();
122 #if 0
123 /* Locking mechanism for userspace */
124 void *ExecLock__AllocLock()
126 spinlock_t *publicLock;
128 D(bug("[Exec:Lock] %s()\n", __func__));
130 if ((publicLock = (spinlock_t *)AllocMem(sizeof(spinlock_t), MEMF_ANY)) != NULL)
132 EXEC_SPINLOCK_INIT(publicLock);
134 return publicLock;
137 void *ExecLock__ObtainLock(void *lock, ULONG mode)
139 D(bug("[Exec:Lock] %s()\n", __func__));
141 if (lock)
143 EXEC_SPINLOCK_LOCK(lock, NULL, mode);
144 return (void *)TRUE;
146 return NULL;
149 void ExecLock__ReleaseLock(void *lock)
151 D(bug("[Exec:Lock] %s()\n", __func__));
153 if (lock)
155 EXEC_SPINLOCK_UNLOCK(lock);
159 void ExecLock__FreeLock(void *lock)
161 D(bug("[Exec:Lock] %s()\n", __func__));
163 if (lock)
165 FreeMem(lock, sizeof(spinlock_t));
168 #endif
170 AROS_LH1 (struct ExecLockBase *, ResourceOpen,
171 AROS_LHA (ULONG, version, D0),
172 struct ExecLockBase *, ExecLockBase, 1, ExecLock
175 AROS_LIBFUNC_INIT
177 D(bug("[Exec:Lock] %s()\n", __func__));
179 ((struct Library *)ExecLockBase)->lib_OpenCnt++;
180 ((struct Library *)ExecLockBase)->lib_Flags &= ~LIBF_DELEXP;
182 return ExecLockBase;
184 AROS_LIBFUNC_EXIT
187 AROS_LH3 (int, ObtainSystemLock,
188 AROS_LHA(struct List *, systemList, A0),
189 AROS_LHA(ULONG, mode, D0),
190 AROS_LHA(ULONG, flags, D1),
191 struct ExecLockBase *, ExecLockBase, 5, ExecLock
194 AROS_LIBFUNC_INIT
196 D(bug("[Exec:Lock] %s()\n", __func__));
198 return ExecLock__InternObtainSystemLock(systemList, mode, flags);
200 AROS_LIBFUNC_EXIT
203 AROS_LH2 (void, ReleaseSystemLock,
204 AROS_LHA(struct List *, systemList, A0),
205 AROS_LHA(ULONG, flags, D1),
206 struct ExecLockBase *, ExecLockBase, 6, ExecLock
209 AROS_LIBFUNC_INIT
211 D(bug("[Exec:Lock] %s()\n", __func__));
213 ExecLock__InternReleaseSystemLock(systemList, flags);
215 AROS_LIBFUNC_EXIT
219 const APTR ExecLock__FuncTable[]=
221 &AROS_SLIB_ENTRY(ResourceOpen,ExecLock,1),
222 NULL,
223 NULL,
224 NULL,
225 /* Version 36 */
226 &AROS_SLIB_ENTRY(ObtainSystemLock,ExecLock,5),
227 &AROS_SLIB_ENTRY(ReleaseSystemLock,ExecLock,6),
228 (void *)-1
232 APTR ExecLock__PrepareBase(struct MemHeader *mh)
234 APTR ExecLockResBase;
235 struct ExecLockBase *ExecLockBase;
237 D(bug("[Exec:Lock] %s()\n", __func__));
239 ExecLockResBase = Allocate(mh, sizeof(struct ExecLockBase) + sizeof(*ExecLock__FuncTable));
240 ExecLockBase = (struct ExecLockBase *)((IPTR)ExecLockResBase + sizeof(*ExecLock__FuncTable));
242 MakeFunctions(ExecLockBase, ExecLock__FuncTable, NULL);
244 ExecLockBase->el_Node.ln_Name = "execlock.resource";
245 ExecLockBase->el_Node.ln_Type = NT_RESOURCE;
246 ExecLockBase->ObtainSystemLock = ExecLock__InternObtainSystemLock;
247 ExecLockBase->ReleaseSystemLock = ExecLock__InternReleaseSystemLock;
249 AddResource(ExecLockBase);
251 return ExecLockBase;
254 #endif