moo/stix/kernel/Process.st

429 lines
6.9 KiB
Smalltalk
Raw Normal View History

2015-10-15 14:40:08 +00:00
#class(#pointer) Process(Object)
{
#dcl initial_context current_context state sp prev next sem.
#method new
{
"instantiation is not allowed"
^nil. "TODO: raise an exception"
}
2015-10-15 14:40:08 +00:00
#method prev
{
^self.prev.
}
#method next
{
^self.next.
}
#method next: process
2015-10-15 14:40:08 +00:00
{
self.next := process.
2015-10-15 14:40:08 +00:00
}
#method prev: process
2015-10-15 14:40:08 +00:00
{
self.prev := process.
2015-10-15 14:40:08 +00:00
}
2015-10-18 15:06:17 +00:00
#method resume
{
<primitive: #_process_resume>
self primitiveFailed
##^Processor resume: self.
2015-10-18 15:06:17 +00:00
}
#method _terminate
2016-02-14 06:35:18 +00:00
{
<primitive: #_process_terminate>
self primitiveFailed
}
#method terminate
{
##search from the top contextof the process down to intial_contextand find ensure blocks and execute them.
self.current_context unwindTo: self.initial_context return: nil.
^self _terminate
}
#method yield
{
<primitive: #_process_yield>
self primitiveFailed
}
#method sp
{
^self.sp.
}
#method initialContext
{
^self.initial_context
}
2015-10-15 14:40:08 +00:00
}
#class Semaphore(Object)
{
#dcl count waiting_head waiting_tail heapIndex fireTimeSec fireTimeNsec.
2016-05-18 15:10:00 +00:00
#method(#class) forMutualExclusion
{
| sem |
sem := self new.
sem signal.
^sem
}
#method initialize
{
2016-03-16 02:27:18 +00:00
self.count := 0.
2016-03-16 14:05:34 +00:00
self.heapIndex := -1.
self.fireTimeSec := 0.
self.fireTimeNsec := 0.
}
## ==================================================================
#method signal
{
<primitive: #_semaphore_signal>
self primitiveFailed.
}
#method wait
{
<primitive: #_semaphore_wait>
self primitiveFailed.
}
2016-03-16 02:27:18 +00:00
#method waitWithTimeout: seconds
{
<primitive: #_semaphore_wait>
self primitiveFailed
}
#method waitWithTimeout: seconds and: nanoSeconds
{
<primitive: #_semaphore_wait>
self primitiveFailed
}
#method critical: aBlock
{
self wait.
^aBlock ensure: [ self signal ]
}
## ==================================================================
2016-03-16 02:27:18 +00:00
#method heapIndex
{
^heapIndex
}
#method heapIndex: anIndex
{
heapIndex := anIndex
}
#method fireTime
{
^fireTimeSec
2016-03-16 02:27:18 +00:00
}
#method fireTime: anInteger
{
self.fireTimeSec := anInteger.
2016-03-16 02:27:18 +00:00
}
#method youngerThan: aSemaphore
{
^self.fireTimeSec < (aSemaphore fireTime)
2016-03-16 02:27:18 +00:00
}
}
#class SemaphoreHeap(Object)
{
#dcl arr size.
#method initialize
{
self.size := 0.
self.arr := Array new: 100.
}
#method size
{
^self.size
}
#method at: anIndex
{
^self.arr at: anIndex.
}
2016-03-16 02:27:18 +00:00
#method insert: aSemaphore
{
2016-03-16 14:05:34 +00:00
| index |
index := self.size.
(index >= (self.arr size)) ifTrue: [
2016-03-16 02:27:18 +00:00
| newarr newsize |
newsize := (self.arr size) * 2.
newarr := Array new: newsize.
newarr copy: self.arr.
self.arr := newarr.
].
2016-03-16 14:05:34 +00:00
self.arr at: index put: aSemaphore.
aSemaphore heapIndex: index.
2016-03-16 02:27:18 +00:00
self.size := self.size + 1.
2016-03-16 14:05:34 +00:00
^self siftUp: index
2016-03-16 02:27:18 +00:00
}
#method popTop
{
| top |
2016-03-16 14:05:34 +00:00
top := self.arr at: 0.
self deleteAt: 0.
2016-03-16 02:27:18 +00:00
^top
}
#method updateAt: anIndex with: aSemaphore
2016-03-16 02:27:18 +00:00
{
| item |
item := self.arr at: anIndex.
item heapIndex: -1.
self.arr at: anIndex put: aSemaphore.
aSemaphore heapIndex: anIndex.
^(aSemaphore youngerThan: item)
ifTrue: [ self siftUp: anIndex ]
ifFalse: [ self siftDown: anIndex ].
2016-03-16 02:27:18 +00:00
}
#method deleteAt: anIndex
{
| item |
item := self.arr at: anIndex.
item heapIndex: -1.
2016-03-16 14:05:34 +00:00
self.size := self.size - 1.
2016-03-16 02:27:18 +00:00
(anIndex == self.size)
ifTrue: [
"the last item"
self.arr at: self.size put: nil.
]
ifFalse: [
| xitem |
xitem := self.arr at: self.size.
self.arr at: anIndex put: xitem.
xitem heapIndex: anIndex.
self.arr at: self.size put: nil.
(xitem youngerThan: item)
ifTrue: [self siftUp: anIndex ]
ifFalse: [self siftDown: anIndex ]
]
}
#method parentIndex: anIndex
{
2016-03-16 14:05:34 +00:00
^(anIndex - 1) quo: 2
2016-03-16 02:27:18 +00:00
}
#method leftChildIndex: anIndex
{
2016-03-16 14:05:34 +00:00
^(anIndex * 2) + 1.
2016-03-16 02:27:18 +00:00
}
#method rightChildIndex: anIndex
{
2016-03-16 14:05:34 +00:00
^(anIndex * 2) + 2.
2016-03-16 02:27:18 +00:00
}
#method siftUp: anIndex
{
| pindex cindex par item stop |
2016-03-16 02:27:18 +00:00
2016-03-16 14:05:34 +00:00
(anIndex <= 0) ifTrue: [ ^anIndex ].
2016-03-16 02:27:18 +00:00
pindex := anIndex.
item := self.arr at: anIndex.
2016-03-16 02:27:18 +00:00
stop := false.
[ stop ] whileFalse: [
2016-03-16 02:27:18 +00:00
cindex := pindex.
2016-03-16 14:05:34 +00:00
(cindex > 0)
ifTrue: [
pindex := self parentIndex: cindex.
par := self.arr at: pindex.
(item youngerThan: par)
ifTrue: [
## move the parent down
self.arr at: cindex put: par.
par heapIndex: cindex.
]
ifFalse: [ stop := true ].
]
ifFalse: [ stop := true ].
2016-03-16 02:27:18 +00:00
].
self.arr at: cindex put: item.
item heapIndex: cindex.
2016-03-16 02:27:18 +00:00
^cindex
}
#method siftDown: anIndex
{
| base capa cindex item |
2016-03-16 14:05:34 +00:00
base := self.size quo: 2.
(anIndex >= base) ifTrue: [^anIndex].
2016-03-16 02:27:18 +00:00
cindex := anIndex.
item := self.arr at: cindex.
[ cindex < base ] whileTrue: [
| left right younger xitem |
left := self leftChildIndex: cindex.
right := self rightChildIndex: cindex.
2016-03-16 14:05:34 +00:00
((right < self.size) and: [(self.arr at: right) youngerThan: (self.arr at: left)])
2016-03-16 02:27:18 +00:00
ifTrue: [ younger := right ]
ifFalse: [ younger := left ].
xitem := self.arr at: younger.
(item youngerThan: xitem)
ifTrue: [
"break the loop"
base := anIndex
]
ifFalse: [
self.arr at: cindex put: xitem.
xitem heapIndex: cindex.
cindex := younger.
]
].
self.arr at: cindex put: item.
item heapIndex: cindex.
^cindex
}
}
2015-10-15 14:40:08 +00:00
#class ProcessScheduler(Object)
{
2016-03-16 02:27:18 +00:00
#dcl tally active runnable_head runnable_tail sem_heap.
2015-10-15 14:40:08 +00:00
#method new
{
"instantiation is not allowed"
^nil. "TODO: raise an exception"
}
#method activeProcess
{
^self.active.
}
#method resume: process
{
<primitive: #_processor_schedule>
self primitiveFailed.
2015-10-15 14:40:08 +00:00
"The primitive does something like the following in principle:
2015-10-15 14:40:08 +00:00
(self.tally = 0)
ifTrue: [
self.head := process.
self.tail := process.
2015-10-15 14:40:08 +00:00
self.tally := 1.
]
ifFalse: [
process next: self.head.
self.head prev: process.
self.head := process.
2015-10-15 14:40:08 +00:00
self.tally := self.tally + 1.
].
"
2015-10-18 15:06:17 +00:00
}
2015-10-15 14:40:08 +00:00
"
#method yield
{
<primitive: #_processor_yield>
2015-10-15 14:40:08 +00:00
self primitiveFailed
}
"
2016-03-16 02:27:18 +00:00
#method signal: semaphore after: secs
2016-03-16 02:27:18 +00:00
{
<primitive: #_processor_add_timed_semaphore>
self primitiveFailed.
}
#method signal: semaphore after: secs and: nanosecs
{
<primitive: #_processor_add_timed_semaphore>
self primitiveFailed.
2016-03-16 02:27:18 +00:00
}
#method unsignal: semaphore
{
<primitive: #_processor_remove_semaphore>
self primitiveFailed.
}
"#method signal: semaphore onInput: file
{
}"
"#method signal: semaphore onOutput: file
{
}"
#method return: object to: context
{
<primitive: #_processor_return_to>
self primitiveFailed.
}
#method sleepFor: secs
{
## -----------------------------------------------------
## put the calling process to sleep for given seconds.
## -----------------------------------------------------
| s |
s := Semaphore new.
self signal: s after: secs.
s wait.
}
#method sleepFor: secs and: nanosecs
{
## -----------------------------------------------------
## put the calling process to sleep for given seconds.
## -----------------------------------------------------
| s |
s := Semaphore new.
self signal: s after: secs and: nanosecs
s wait.
}
2015-10-15 14:40:08 +00:00
}