]> git.buserror.net Git - polintos/scott/priv.git/blob - kernel/core/lock.cc
5f046dff2764df8373de4a7bb92107b5ec02a71e
[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 // Permission is hereby granted, free of charge, to any person obtaining a copy of
6 // this software and associated documentation files (the "Software"), to deal with
7 // the Software without restriction, including without limitation the rights to
8 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9 // of the Software, and to permit persons to whom the Software is furnished to do
10 // so, subject to the following conditions:
11 // 
12 //     * Redistributions of source code must retain the above copyright notice,
13 //       this list of conditions and the following disclaimers.
14 // 
15 //     * Redistributions in binary form must reproduce the above copyright notice,
16 //       this list of conditions and the following disclaimers in the
17 //       documentation and/or other materials provided with the distribution.
18 // 
19 //     * The names of the Software's authors and/or contributors
20 //       may not be used to endorse or promote products derived from
21 //       this Software without specific prior written permission.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
25 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
26 // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
29 // SOFTWARE.
30
31 #include <util/lock.h>
32 #include <kern/thread.h>
33
34 namespace Lock {
35         // OPT: add inline, lockless uncontended case
36
37         // FIXME: Allow a high-priority blocker to steal a lock from
38         // a low-priority holder if the holder has not yet run.  This
39         // prevents rescheduling every iteration if both threads are
40         // repeatedly acquiring and releasing the lock.
41         
42         void Lock::lock()
43         {
44                 DroppableAutoSpinLockRecIRQ autolock(spinlock);
45                 
46                 if (!lockval) {
47                         lockval = reinterpret_cast<ulong>(curthread);
48                         return;
49                 }
50                 
51                 assert(lockval != reinterpret_cast<ulong>(curthread));
52                 
53                 Threads::ThreadBlocker blocker(curthread);
54                 waitqueue.block(&blocker);
55                 
56                 if (!lockval) {
57                         lockval = reinterpret_cast<ulong>(curthread);
58                         waitqueue.unblock(&blocker);
59                         return;
60                 }
61                 
62                 autolock.unlock();
63                 curthread->block(&blocker);
64                 
65                 // FIXME: interruptible locks
66                 assert(lockval == reinterpret_cast<ulong>(curthread));
67         }
68         
69         void Lock::unlock()
70         {
71                 AutoSpinLockRecIRQ autolock(spinlock);
72                 assert(lockval == reinterpret_cast<ulong>(curthread));
73                 
74                 if (waitqueue.empty()) {
75                         lockval = 0;
76                         return;
77                 }
78                 
79                 Threads::Blocker *b = waitqueue.unblock_one();
80                 lockval = reinterpret_cast<ulong>(b->thread);
81                 b->wake();
82         }
83 }