]> git.buserror.net Git - polintos/scott/priv.git/blob - kernel/core/lock.cc
Use -freg-struct-return.
[polintos/scott/priv.git] / kernel / core / lock.cc
1 // core/thread.cc -- Scheduler and thread creation/destruction
2 //
3 // This software is copyright (c) 2006 Scott Wood <scott@buserror.net>.
4 // 
5 // This software is provided 'as-is', without any express or implied warranty.
6 // In no event will the authors or contributors be held liable for any damages
7 // arising from the use of this software.
8 // 
9 // Permission is hereby granted to everyone, free of charge, to use, copy,
10 // modify, prepare derivative works of, publish, distribute, perform,
11 // sublicense, and/or sell copies of the Software, provided that the above
12 // copyright notice and disclaimer of warranty be included in all copies or
13 // substantial portions of this software.
14
15 #include <util/lock.h>
16 #include <kern/thread.h>
17
18 namespace Lock {
19         // OPT: add inline, lockless uncontended case
20
21         // FIXME: Allow a high-priority blocker to steal a lock from
22         // a low-priority holder if the holder has not yet run.  This
23         // prevents rescheduling every iteration if both threads are
24         // repeatedly acquiring and releasing the lock.
25         
26         void Lock::lock()
27         {
28                 DroppableAutoSpinLockRecIRQ autolock(spinlock);
29                 
30                 if (!lockval) {
31                         lockval = reinterpret_cast<ulong>(curthread);
32                         return;
33                 }
34                 
35                 assert(lockval != reinterpret_cast<ulong>(curthread));
36                 
37                 Threads::ThreadBlocker blocker(curthread);
38                 waitqueue.block(&blocker);
39                 
40                 if (!lockval) {
41                         lockval = reinterpret_cast<ulong>(curthread);
42                         waitqueue.unblock(&blocker);
43                         return;
44                 }
45                 
46                 autolock.unlock();
47                 curthread->block(&blocker);
48                 
49                 // FIXME: interruptible locks
50                 assert(lockval == reinterpret_cast<ulong>(curthread));
51         }
52         
53         void Lock::unlock()
54         {
55                 AutoSpinLockRecIRQ autolock(spinlock);
56                 assert(lockval == reinterpret_cast<ulong>(curthread));
57                 
58                 if (waitqueue.empty()) {
59                         lockval = 0;
60                         return;
61                 }
62                 
63                 Threads::Blocker *b = waitqueue.unblock_one();
64                 lockval = reinterpret_cast<ulong>(b->thread);
65                 b->wake();
66         }
67 }