|
1 .include "DS.S" |
|
2 #----------------------------------------------- |
|
3 # S T A T I C V A R I A B L E S |
|
4 #----------------------------------------------- |
|
5 .data |
|
6 .global C.csP |
|
7 C.csP: .int 0 # -->CS |
|
8 .text |
|
9 #----------------------------------------------- |
|
10 # M A I N R O U T I N E |
|
11 #----------------------------------------------- |
|
12 # takes values from ENV, establishes task for comm nodes and waits for their completion |
|
13 ARGS |
|
14 DS prgP # -->progname |
|
15 # returns nothing |
|
16 PROLOC |
|
17 DL this, CSL # CS - top level attr vector |
|
18 DL deP # -->Debug |
|
19 DL status # status returned from wait |
|
20 DL pid # PID returned from wait |
|
21 DL bad # cummulative subtask rc |
|
22 DL s, 256 # string buf |
|
23 EPILOC |
|
24 #----------------------------------------------- |
|
25 .global _start |
|
26 _start: |
|
27 PROLOG |
|
28 lea this(bp), b # -->CS |
|
29 mov b, C.csP # save -->CS |
|
30 lea C.debug(b), a # -->Debug |
|
31 mov a, deP(bp) |
|
32 # initialize static debug vars |
|
33 push prgP(bp) # argv[0] -->prgname |
|
34 call D.init # initialize static debug vars |
|
35 push D.prgNameP |
|
36 # indetify itself |
|
37 DEBID "client/server demo" |
|
38 movl $1, C.debMaxLev(b) # default debug level |
|
39 # initialize top level ctrl values vector |
|
40 ShareA # allocate shared structure |
|
41 mov C.csP, b |
|
42 mov a, C.shP(b) # save -->shared struct in vector |
|
43 movl $0, S.msgs(a) # init msg cntr |
|
44 movl $0, S.conns(a) # init connection cntr |
|
45 push $1 # initial semaphore value |
|
46 push $1 # semaphore shared between processes |
|
47 lea S.counter_sem(a), c |
|
48 push c |
|
49 # call sem_init # initialize shared counters semaphore |
|
50 # cmp $0, a |
|
51 # jz 0f |
|
52 # SYSERR "sem_init of shared counters semaphore" |
|
53 #0: |
|
54 SYS sem_init |
|
55 # set default values |
|
56 mov C.csP, b |
|
57 movl $3, C.ttl(b) # default TTL |
|
58 movl $11000, C.rp0(b) # default bind port for the 1. node in ring |
|
59 movl $12000, C.mp0(b) # default bind port for the 1. node in mash |
|
60 movl $0, C.rn(b) # default # of nodes in ring |
|
61 movl $0, C.mn(b) # default # of nodes in mash |
|
62 movl $0, C.ssl(b) # default ssl switch - 0=noSSL |
|
63 movl $77, C.connTh(b) # conn retries threshold |
|
64 mov $0f, a |
|
65 mov a, C.txtP(b) # default payload text |
|
66 jmp 1f |
|
67 0: .ascii "bla bla\0" |
|
68 1: |
|
69 # get control values from ENV |
|
70 # get max debug level |
|
71 GETINTENV "DEB" |
|
72 mov C.csP, b |
|
73 mov a, C.debMaxLev(b) |
|
74 cmp $-1, a # debug level -1 means search subroutines |
|
75 jne 0f |
|
76 call D.subr |
|
77 jmp C.ret |
|
78 0: |
|
79 # get message payload text |
|
80 push $0f |
|
81 call getenv |
|
82 cmp $0, a |
|
83 jz 1f |
|
84 mov C.csP, b |
|
85 mov a, C.txtP(b) |
|
86 jmp 1f |
|
87 0: .asciz "T" |
|
88 1: |
|
89 # get TTL |
|
90 GETINTENV "TTL" |
|
91 jz 0f |
|
92 mov a, C.ttl(b) |
|
93 0: |
|
94 # get # of nodes in each topology |
|
95 GETINTENV "I" |
|
96 jz 0f |
|
97 mov a, C.rn(b) |
|
98 mov a, C.mn(b) |
|
99 0: |
|
100 # get # of nodes in ring |
|
101 GETINTENV "RN" |
|
102 jz 0f |
|
103 mov a, C.rn(b) |
|
104 0: |
|
105 # get # of nodes in mash |
|
106 GETINTENV "MN" |
|
107 jz 0f |
|
108 mov a, C.mn(b) |
|
109 0: |
|
110 add C.rn(b), a |
|
111 cmp $3, C.ssl(b) |
|
112 jne 1f |
|
113 add a, a # double # of nodes when both SSL and nonSSL |
|
114 1: mov C.shP(b), c # -->shared counters |
|
115 mov a, S.act(c) # save # of active nodes |
|
116 # get first ring node's bind port# |
|
117 GETINTENV "RP0" |
|
118 jz 0f |
|
119 mov a, C.rp0(b) |
|
120 0: |
|
121 # get first mash node's bind port# |
|
122 GETINTENV "MP0" |
|
123 jz 0f |
|
124 mov a, C.mp0(b) |
|
125 0: |
|
126 # get random() seed |
|
127 GETINTENV "RS" |
|
128 jz 0f |
|
129 push a |
|
130 call srandom |
|
131 0: |
|
132 # get pacing interval (real num in seconds) |
|
133 movl $0, C.pace.tv_sec(b) |
|
134 movl $0, C.pace.tv_nsec(b) |
|
135 movl $0, C.pacing(b) |
|
136 push $0f |
|
137 call getenv |
|
138 jmp 1f |
|
139 0: .asciz "P" |
|
140 1: |
|
141 test a, a # env P set ? |
|
142 jz 3f # no |
|
143 push a |
|
144 call atof # convert to double |
|
145 fstl (sp) # tempor save |
|
146 mov C.csP, b |
|
147 fisttpl C.pace.tv_sec(b) # truncated integral part = secs |
|
148 fldl (sp) |
|
149 fisubl C.pace.tv_sec(b) # fraction part |
|
150 fimull 1f # * 10^9 = nanosecs |
|
151 fistl C.pace.tv_nsec(b) |
|
152 jmp 2f |
|
153 0: .double 0 |
|
154 1: .int 1000000000 # 10^9 |
|
155 2: |
|
156 cmp $0, C.pace.tv_sec(b) |
|
157 jnz 0f |
|
158 cmp $0, C.pace.tv_nsec(b) |
|
159 jz 3f |
|
160 0: movl $1, C.pacing(b) |
|
161 3: |
|
162 # get ssl switch value and save it as mask |
|
163 # switch: 0 = noSSL, 1 = SSL, 2 = both |
|
164 # mask: 01B=noSSL, 10B=SSL, 11B=both |
|
165 GETINTENV "SSL" # returned zero means SSL=0 or SSL by default 0 |
|
166 inc a # change switch to mask |
|
167 mov a, C.ssl(b) |
|
168 cmp $1, a |
|
169 je C.cont # no SSL |
|
170 cmp $2, a |
|
171 je 0f # only SSL |
|
172 mov C.shP(b), a # -->shared mem |
|
173 shll $1, S.act(a) # double # of active nodes when running both SSL and nonSSL |
|
174 # get SSL CA cert dir path |
|
175 0: |
|
176 push $0f |
|
177 call getenv |
|
178 jmp 1f |
|
179 0: .asciz "CAP" |
|
180 1: |
|
181 test a, a |
|
182 jnz 1f |
|
183 mov $0f, a |
|
184 jmp 1f |
|
185 0: .asciz "/home/local/etc/ssl/certs/" |
|
186 1: |
|
187 mov C.csP, b |
|
188 mov a, C.caPathP(b) # save -->SSL CA certs path |
|
189 # get SSL dir path |
|
190 push $0f |
|
191 call getenv |
|
192 jmp 1f |
|
193 0: .asciz "CEP" |
|
194 1: |
|
195 test a, a |
|
196 jz 0f # ceP not set, try to determine |
|
197 mov C.csP, b |
|
198 mov a, C.cePathP(b) # save -->SSL dir path |
|
199 jmp 1f |
|
200 # determine home path (needed to locate SSL keys & certificates) |
|
201 0: |
|
202 push prgP(bp) # -->first parm - progname w/ path |
|
203 call dirname # get prog dirname |
|
204 push a |
|
205 call strlen # dirname length |
|
206 lea 1f-0f(a), a # + suffix length |
|
207 sub a, sp # allocate space for cePath |
|
208 mov C.csP, b |
|
209 mov sp, C.cePathP(b) # save -->SSL path |
|
210 push prgP(bp) |
|
211 call dirname # get home dirname |
|
212 push a # -->home dirname |
|
213 mov C.csP, b |
|
214 push C.cePathP(b) # -->SSL path |
|
215 call strcpy # copy dirname to SSL path |
|
216 call strlen # end of dirname |
|
217 push $0f # -->suffix |
|
218 mov C.csP, b |
|
219 mov C.cePathP(b), c |
|
220 lea (c, a), a # -->end of dirname |
|
221 push a |
|
222 call strcpy # copy suffix to SSL path |
|
223 jmp 1f |
|
224 0: .asciz "/../CS/" |
|
225 1: |
|
226 # testing sandbox |
|
227 mov C.csP, b |
|
228 pushl C.debMaxLev(b) |
|
229 cmp $9, C.debMaxLev(b) |
|
230 jne C.cont |
|
231 |
|
232 LOG 9, "debug=%u, testing...", 1 |
|
233 DebugA |
|
234 mov a, deP(bp) |
|
235 DEBID "TEST" |
|
236 LOG 9, "progress" |
|
237 |
|
238 mov C.csP, b |
|
239 mov C.shP(b), a |
|
240 push S.act(a) |
|
241 LOG 9, "shared act=%u" |
|
242 |
|
243 jmp C.ret |
|
244 # normal execution |
|
245 C.cont: |
|
246 push C.debMaxLev(b) |
|
247 push C.ssl(b) |
|
248 push C.pace.tv_nsec(b) |
|
249 push C.pace.tv_sec(b) |
|
250 push C.ttl(b) |
|
251 push C.rn(b) |
|
252 push C.mn(b) |
|
253 push D.prgNameP |
|
254 LOG 1, "pgm=%s, mash nodes=%d, ring nodes=%d, ttl=%d, pacing=%ld.%09ld, SSL mask=0x%02x, debug=%u", 8 |
|
255 testl $2, C.ssl(b) |
|
256 jz 0f |
|
257 push C.caPathP(b) |
|
258 push C.cePathP(b) |
|
259 LOG 1, "SSL path=%s, SSL CA path=%s" |
|
260 0: |
|
261 # create constellation processes RING/MASH, nonSSL/SSL |
|
262 mov $0, c # iter counter |
|
263 mov C.ssl(b), d # SSL mask (01b = noSSL, 10b = SSL, 11b = both) |
|
264 # iterate on SSL variants |
|
265 C.iterateOnSsl: |
|
266 test $1, d # check lowest bit of mask |
|
267 jz C.nextSsslVar # next SSL variant |
|
268 pusha |
|
269 # create RING |
|
270 SYS fork |
|
271 jnz 1f # parent |
|
272 popa |
|
273 pushl $Cn.ring # RING topology |
|
274 push c # use iter ctr as SSL switch |
|
275 call Constellation # create RING constellation |
|
276 1: push a |
|
277 LOG 5, "RING started in process %d" |
|
278 lea 4(sp), sp |
|
279 # create MASH |
|
280 SYS fork |
|
281 jnz 1f # parent |
|
282 popa |
|
283 pushl $Cn.mash # MASH topology |
|
284 push c # use iter ctr as SSL switch |
|
285 call Constellation # create MASH constellation |
|
286 1: push a |
|
287 LOG 5, "MASH started in process %d" |
|
288 lea 4(sp), sp |
|
289 |
|
290 popa |
|
291 C.nextSsslVar: |
|
292 shr $1, d # shift to test next SSL bit |
|
293 inc c # incr ctr |
|
294 cmp $2, c |
|
295 jl C.iterateOnSsl |
|
296 # wait for constellation processes completion |
|
297 LOG 5, "waiting for constellations to terminate" |
|
298 movl $0, bad(bp) # clear cummulative rc |
|
299 C.iterateOnWait: |
|
300 lea status(bp), a |
|
301 push a # -->return status of task |
|
302 call wait |
|
303 mov a, pid(bp) # save pid |
|
304 cmp $-1, a # a task ended? |
|
305 jne 0f # yes |
|
306 call __errno_location |
|
307 cmp $10, (a) # error == ECHILD ? |
|
308 je C.ret # yes, no other subtasks |
|
309 SYSERR "wait" |
|
310 0: |
|
311 # push status(bp) # status of task |
|
312 # push a # pid |
|
313 # LOG 5, "status returned from task %u: 0x%08x" |
|
314 mov status(bp), d |
|
315 test $0x7f, d |
|
316 jnz 1f # task killed, ABEND |
|
317 and $0xff00, d # task exited, extract rc |
|
318 shr $8, d |
|
319 or d, bad(bp) # accumulate rc |
|
320 push d # task rc |
|
321 push pid(bp) # task pid |
|
322 LOG 5, "constellation task %u ended with exit(%d)" |
|
323 jmp C.iterateOnWait # wait for other tasks |
|
324 1: push d |
|
325 push pid(bp) |
|
326 LOG 5, "constellation task %u killed, status=0x%x", 2 |
|
327 2: |
|
328 # ABEND |
|
329 LOG 0, "ABEND, kill all tasks" |
|
330 pushl $15 # SIGTERM |
|
331 pushl $0 # all tasks |
|
332 # call kill |
|
333 SYS kill |
|
334 pushl $1 |
|
335 call exit |
|
336 # normal end |
|
337 C.ret: movl C.csP, b # -->CS vector |
|
338 movl C.shP(b), b # -->Share |
|
339 pushl S.conns(b) # no. of connections made |
|
340 pushl S.msgs(b) # no. of messages sent |
|
341 LOG 1, "END, forwards=%d, connections=%d", 2 |
|
342 push bad(bp) |
|
343 call exit |
|
344 #----------------------------------------------- |
|
345 # C O N S T E L L A T I O N O P E R A T I O N S |
|
346 #----------------------------------------------- |
|
347 ARGS |
|
348 DS ssl # ssl switch |
|
349 DS topo # topology |
|
350 # returns: nothing |
|
351 PROLOC |
|
352 DL this, ConstellationL # this Constellation instance |
|
353 DL thisP # -->this Constellation |
|
354 DL deP # -->Debug |
|
355 DL last # last node# |
|
356 DL pid # pid returned from wait |
|
357 DL stat # stat returned from wait |
|
358 DL bad # "some node BAD" exit indicator |
|
359 DL catched # count of returned node tasks |
|
360 DL killed # count of killed node tasks |
|
361 EPILOC |
|
362 #----------------------------------------------- |
|
363 .global Constellation |
|
364 Constellation: |
|
365 PROLOG |
|
366 lea this(bp), b # -->this Constellation |
|
367 mov b, thisP(bp) # save -->this Constellation |
|
368 # set debid |
|
369 lea Cn.debug(b), a # -->Debug |
|
370 mov a, deP(bp) # save -->Debug locally |
|
371 mov C.csP, c # -->CS |
|
372 cmp $Cn.ring, topo(bp) # ring topology ? |
|
373 je 0f |
|
374 mov C.mn(c), a # num. of nodes |
|
375 mov a, Cn.nodes(b) |
|
376 mov C.mp0(c), a # port # of fist node |
|
377 mov a, Cn.first(b) |
|
378 movl $Cn.mash, Cn.topo(b) |
|
379 push $8f |
|
380 jmp 1f |
|
381 0: mov C.rn(c), a # num. of nodes |
|
382 mov a, Cn.nodes(b) |
|
383 mov C.rp0(c), a # port # of fist node |
|
384 mov a, Cn.first(b) |
|
385 movl $Cn.ring, Cn.topo(b) |
|
386 push $7f |
|
387 1: cmp $0, ssl(bp) # SSL ? |
|
388 jz 2f # no |
|
389 movl $1, Cn.ssl(b) |
|
390 addl $500, Cn.first(b) # first SSL port # |
|
391 push $6f |
|
392 jmp 9f |
|
393 2: movl $0, Cn.ssl(b) |
|
394 push $5f |
|
395 jmp 9f |
|
396 5: .ascii "non\0" |
|
397 6: .ascii "\0" |
|
398 7: .ascii "RING\0" |
|
399 8: .ascii "MASH\0" |
|
400 9: DEBID "%sSSL %s", 2 |
|
401 # check # of nodes |
|
402 movL $0, bad(bp) |
|
403 cmp $1, Cn.nodes(b) # num of nodes |
|
404 jl Cn.ret # < 1 ? nothing to do |
|
405 jg 0f |
|
406 LOG 0, "1 node configuration not implemented yet" |
|
407 jmp Cn.ret |
|
408 0: LOG 5, "initializing..." |
|
409 # determine divisor for random next node choise |
|
410 mov $1, a |
|
411 shl $31, a |
|
412 not a # MAX_INT |
|
413 xor d, d |
|
414 divl Cn.nodes(b) |
|
415 mov a, Cn.div(b) # save divisor (MAX_INT / nodes) |
|
416 # allocate "forward" indicator shared by nodes in constellation |
|
417 push $0 |
|
418 push $-1 |
|
419 push $0x21 # PROT_READ | PROT_WRITE |
|
420 push $0x03 # MAP_SHARED | MAP_ANONYMOUS |
|
421 push $4 |
|
422 push $0 |
|
423 # call mmap |
|
424 # cmp $-1, a |
|
425 # jne 0f |
|
426 # SYSERR "mmap" |
|
427 #0: mov thisP(bp), b |
|
428 SYS mmap |
|
429 mov a, Cn.forwP(b) # save -->forw |
|
430 movl $1, (a) # enable forwarding |
|
431 push Cn.nodes(b) |
|
432 LOG 1, "%u nodes starting..." |
|
433 # start processes for all nodes in constellation |
|
434 mov Cn.first(b), d # first node# |
|
435 mov d, c |
|
436 add Cn.nodes(b), c # last node + 1 |
|
437 Cn.iterateOnFork: |
|
438 pusha |
|
439 # call fork |
|
440 SYS fork |
|
441 cmp $0, a |
|
442 jnz 1f # parent |
|
443 popa |
|
444 push d # node's port# |
|
445 push b # -->Cnstlln |
|
446 call Node |
|
447 1: mov a, pid(bp) |
|
448 popa |
|
449 push pid(bp) # nodes's pid |
|
450 push d # node's port# |
|
451 LOG 4, "node %u established in process %u", 2 |
|
452 inc d |
|
453 cmp d, c # last node ? |
|
454 jg Cn.iterateOnFork # no, continue forking |
|
455 # wait for completion of node processes |
|
456 LOG 2, "all nodes established, waiting for them to terminate..." |
|
457 movl $0, bad(bp) # accumulated return status of node tasks |
|
458 movl $0, killed(bp) # num. of killed node tasks |
|
459 movl $0, catched(bp) # num. of returned node tasks |
|
460 lea -12(sp), sp # prepare space for loop |
|
461 Cn.iterateOnWait: |
|
462 cmp $0, bad(bp) # constellation status still OK ? |
|
463 je 1f # yes |
|
464 mov Cn.forwP(b), a # -->forwarding switch |
|
465 movl $0, (a) # disable forwarding between nodes |
|
466 1: |
|
467 lea stat(bp), c |
|
468 mov c, (sp) # -->return status of task |
|
469 call wait |
|
470 mov thisP(bp), b |
|
471 cmp $-1, a # normal return from wait? |
|
472 jne 0f # yes |
|
473 call __errno_location |
|
474 cmp $10, (a) # error == ECHILD ? |
|
475 je Cn.allFinished # yes, no subtasks |
|
476 SYSERR "wait" |
|
477 0: |
|
478 incl catched(bp) |
|
479 mov a, pid(bp) # save subtask's pid |
|
480 mov a, (sp) |
|
481 mov stat(bp), c # subtask return status |
|
482 mov c, 4(sp) |
|
483 test $0x7f, c # subtask ended by exit ? |
|
484 jnz 2f # no, killed |
|
485 and $0xff00, c # extract subtask rc |
|
486 jz 1f # rc = 0 |
|
487 movl $1, bad(bp) # non zero rc, turn on BAD switch |
|
488 1: shr $8, c |
|
489 mov c, 4(sp) # rc |
|
490 mov a, (sp) # pid |
|
491 LOG 4, "node process %u ended by exit(%d)" |
|
492 jmp Cn.iterateOnWait # continue waiting for other subtasks |
|
493 2: movl $1, bad(bp) # subtask killed, turn on BAD switch |
|
494 incl killed(bp) # counter of killed |
|
495 mov c, 4(sp) # status |
|
496 mov a, (sp) # pid |
|
497 LOG 4, "node process %u killed, status=0x%x" |
|
498 jmp Cn.iterateOnWait # continue waiting for other subtasks |
|
499 |
|
500 # opers of all nodes finished |
|
501 Cn.allFinished: |
|
502 push killed(bp) |
|
503 push catched(bp) |
|
504 mov thisP(bp), b |
|
505 push Cn.nodes(b) |
|
506 cmp $0, bad(bp) # all nodes ended OK ? |
|
507 je 0f # yes |
|
508 push $7f |
|
509 jmp 9f |
|
510 0: push $8f |
|
511 jmp 9f |
|
512 7: .ascii "with ERROR\0" |
|
513 8: .ascii "OK\0" |
|
514 9: LOG 1, "ENDED %s, %u spawned, %u catched, %u killed" |
|
515 Cn.ret: |
|
516 push bad(bp) |
|
517 call exit |
|
518 #----------------------------------------------- |
|
519 # G E T I N T V A L U E S F R O M E N V |
|
520 #----------------------------------------------- |
|
521 ARGS |
|
522 DS key # -->env key string |
|
523 # returns int value or 0 if not found |
|
524 PROLOC |
|
525 EPILOC |
|
526 #----------------------------------------------- |
|
527 C.getArg: |
|
528 PROLOG |
|
529 pushl key(bp) # -->env key string |
|
530 call getenv # get value |
|
531 test a, a |
|
532 jz 0f # not found in ENV |
|
533 push a |
|
534 call atoi # convert to int |
|
535 0: |
|
536 EPILOG_R |
|
537 #----------------------------------------------- |
|
538 # A B N O R M A L E N D |
|
539 #----------------------------------------------- |
|
540 ARGS |
|
541 DS deP # -->Debug |
|
542 PROLOC |
|
543 EPILOC |
|
544 #----------------------------------------------- |
|
545 .globl C.abend |
|
546 C.abend: |
|
547 PROLOG |
|
548 LOG 0, "ABEND" |
|
549 push $15 # SIGTERM |
|
550 push $0 # kill all |
|
551 # call kill |
|
552 SYS kill |
|
553 push $1 |
|
554 call exit |
|
555 #----------------------------------------------- |
|
556 .end |