File: jvm-monitor-primitives.lisp

package info (click to toggle)
acl2 8.6%2Bdfsg-3
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 1,138,276 kB
  • sloc: lisp: 17,818,294; java: 125,359; python: 28,122; javascript: 23,458; cpp: 18,851; ansic: 11,569; perl: 7,678; xml: 5,591; sh: 3,978; makefile: 3,840; ruby: 2,633; yacc: 1,126; ml: 763; awk: 295; csh: 233; lex: 197; php: 178; tcl: 49; asm: 23; haskell: 17
file content (179 lines) | stat: -rw-r--r-- 7,063 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
(in-package "JVM")
(include-book "../M6-DJVM-shared/jvm-state")
(include-book "../M6-DJVM-shared/jvm-obj")
(include-book "../M6-DJVM-shared/jvm-thread")
(include-book "../M6-DJVM-shared/jvm-thread-primitives")


;; temp implementation
;; have implement the clock..
(defun removePendingAlarm (waiter s)
  (declare (ignore waiter))
  s)


(defun registerAlarm (waiter duration s)
  (declare (ignore waiter duration))
  s)

;###



;; lookup the waiting queue of the monitor associated with this class
;; remove those thread from the queue, set thread state back to active. 
;;
;; in our model monitor always exists, 
;; while the ready queue of the system doesn't really exist.
;; 
;; in principle we could maintain all the monitors in a separate list but here
;; we keep the monitor fields in the heap object themselfs.  so any
;; modification of the monitor, in ACL2 we need to create an new object and
;; bind the new object to the same address.


;; isn't it an invariant that all the thread on the mqueue has depth 1?
;; no, it is not true. Because a thread can relinquish the lock on monitor when
;; it start waiting on the conditional variable (cqueue). 

(defun dequeue-h (queue)
  (car queue))
(defun dequeue-r (queue)
  (cdr queue))

(defun obj-monitor-by-ref (obj-ref s)
  (obj-monitor (deref obj-ref (heap s))))

(defun update-obj-monitor (obj-ref m s)
  (let* ((old-heap (heap s))
         (old-obj  (deref obj-ref old-heap))
         (old-common-info (common-info old-obj))
         (new-common-info (common-info-set-monitor m old-common-info))
         (new-obj (obj-set-common-info new-common-info old-obj))
         (new-heap (bind obj-ref new-obj old-heap)))
    (state-set-heap new-heap 
                    s)))

(defun removeMonitorWait-inv (waiter-id s)
  (and (thread-exists? waiter-id (thread-table s))
       (not (equal waiter-id (current-thread s)))
       (wff-thread-table (thread-table s))))




(defun removeMonitorWait (obj-ref s)
  (let* ((m   (obj-monitor-by-ref obj-ref s))
         (mqueue (mqueue m)))
    (if (endp mqueue)
        (let ((new-m (make-monitor -1 ;; no one want
                                   0 
                                   nil
                                   (cqueue m))))
          ;; however some one may be waiting for the condtional variable.
              (update-obj-monitor obj-ref new-m s))
      (let* ((waiter-id (dequeue-h mqueue))
             (old-thread-table (thread-table s))
             (old-thread  (thread-by-id waiter-id old-thread-table))
             (new-m  (make-monitor waiter-id
                                   (thread-mdepth old-thread)
                                   (dequeue-r mqueue)
                                   (cqueue m)))
             (new-thread (thread-set-mref -1  ;; release the monitor
                            (thread-set-mdepth 0 old-thread)))
             (new-thread-table 
                (replace-thread-table-entry old-thread new-thread
                                            old-thread-table)))
        (if (not (removeMonitorWait-inv waiter-id s))
            (fatalError "removeMonitorWait-inv violated" s)
        (update-obj-monitor obj-ref new-m
                            (resumeThread waiter-id (state-set-thread-table new-thread-table s))))))))

;; notice here we didn't really change the monitor that is in the heap.
;; we need to rely on the the caller to take the new monitor returned and set
;; update the monitor fields of the corresponding object.
;; this is internal method. user interface is monitorNotify, ...


;; I didn't see any reason to keep track which monitor the thread is waiting
;; on. except for debug purpose or garbarge collection.
;; why ??? 
;; it is used for timer call back ....

(defun add-to-queue-end (item queue)
  (app queue (list item)))

(defun addMonitorWait (waiter obj-ref s)
  (mylet* ((monitor (obj-monitor-by-ref obj-ref s))
         (old-thread-table (thread-table s))
         (old-thread  (thread-by-id waiter old-thread-table))
         (mqueue      (mqueue monitor))
         (new-mqueue  (add-to-queue-end waiter mqueue))
         (new-thread  (thread-set-mref obj-ref 
                       (set-thread-state-flag 'thread_monitor_wait old-thread)))
         (new-monitor (monitor-set-mqueue new-mqueue monitor))
         (new-thread-table (replace-thread-table-entry 
                            old-thread new-thread old-thread-table))
         (new-state (update-obj-monitor obj-ref new-monitor 
                                        (state-set-thread-table new-thread-table s))))
    (if (equal (owner new-monitor) -1) ;; nobody is holding the thread
        (removeMonitorWait obj-ref  new-state)
      new-state)))


(defun removeCondvarWait2 (waiter obj-ref s)
  (addMonitorWait waiter obj-ref
                  (removePendingAlarm waiter s)))
    
(defun removeCondvarWait1 (queue obj-ref s)
  (if (endp queue)
      (let* ((monitor (obj-monitor-by-ref obj-ref s))
             (new-monitor (monitor-set-cqueue nil monitor))
             (new-state (update-obj-monitor obj-ref new-monitor s)))
        new-state)
    (removeCondvarWait1 (cdr queue) obj-ref
                        (removeCondvarWait2 (car queue) obj-ref s))))


(defun removeCondvarWait (obj-ref notifymode s)
  (let* ((monitor (obj-monitor-by-ref obj-ref s))
         (cqueue  (cqueue monitor)))
    (if (endp cqueue)
        s
      (if (not (equal notifymode 'ALL))
          (let* ((new-monitor 
                  (monitor-set-cqueue (dequeue-r cqueue) monitor))
                 (new-state (update-obj-monitor obj-ref new-monitor s)))
               (removeCondvarWait2 (dequeue-h cqueue) obj-ref new-state))
        (removeCondvarWait1 cqueue obj-ref s)))))


         
                          

(defun addCondvarWait (obj-ref tid s)
  (let* ((monitor (obj-monitor-by-ref obj-ref s))
         (owner   (owner monitor))
         (cqueue  (cqueue monitor)))
    (if (not (equal tid owner))
        (fatalError "bad-call-to-addCondVarWait" s);
      (let* ((new-monitor (monitor-set-cqueue 
                            (add-to-queue-end tid cqueue)
                            monitor))
             (old-thread-table (thread-table s))
             (old-thread (thread-by-id tid old-thread-table))
             (new-thread (thread-set-mdepth (depth monitor)
                                            (set-thread-state-flag 
                                             'thread_convar_wait
                                             (thread-set-mref obj-ref
                                                              old-thread))))
             (new-thread-table (replace-thread-table-entry old-thread
                                                           new-thread
                                                           old-thread-table))
             (new-state (state-set-thread-table new-thread-table 
                              (update-obj-monitor  obj-ref new-monitor s))))
        (removeMonitorWait obj-ref new-state)))))