This source file includes following definitions.
- lock_simh
- unlock_simh
- lock_libuv
- unlock_libuv
- test_libuv_lock
- get_rmw_lock
- lock_rmw
- lock_mem_rd
- lock_mem_wr
- unlock_rmw
- unlock_mem
- unlock_mem_force
- lock_ptr
- unlock_ptr
- lock_scu
- unlock_scu
- lock_iom
- unlock_iom
- lock_tst
- unlock_tst
- test_tst_lock
- rtsched_thread
- pthread_create_with_cpu_policy
- createCPUThread
- stopCPUThread
- cpuRunningWait
- sleepCPU
- wakeCPU
- createIOMThread
- iomInterruptWait
- iomInterruptDone
- iomDoneWait
- setIOMInterrupt
- iomRdyWait
- createChnThread
- chnConnectWait
- chnConnectDone
- setChnConnect
- chnRdyWait
- initThreadz
- setSignals
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <signal.h>
27
28 #include "dps8.h"
29 #include "dps8_sys.h"
30 #include "dps8_cpu.h"
31 #include "dps8_faults.h"
32 #include "dps8_iom.h"
33 #include "dps8_utils.h"
34
35 #include "threadz.h"
36 #if ( defined ( __FreeBSD__ ) || defined ( __OpenBSD__) )
37 # include <pthread_np.h>
38 #endif
39
40 #if defined ( __HAIKU__ )
41 # include <OS.h>
42 # undef pthread_setname_np
43 # define pthread_setname_np(x,y) rename_thread(find_thread(NULL),y)
44 #endif
45
46 #if defined(__MACH__) && defined(__APPLE__) && \
47 ( defined(__PPC__) || defined(_ARCH_PPC) )
48 # include <mach/clock.h>
49 # include <mach/mach.h>
50 # ifdef MACOSXPPC
51 # undef MACOSXPPC
52 # endif
53 # define MACOSXPPC 1
54 #endif
55
56
57
58
59
60
61
62
63 #ifdef IO_ASYNC_PAYLOAD_CHAN_THREAD
64 pthread_cond_t iomCond;
65 pthread_mutex_t iom_start_lock;
66 #endif
67
68 #ifndef QUIET_UNUSED
69 void lock_simh (void)
70 {
71 pthread_mutex_lock (& simh_lock);
72 }
73
74 void unlock_simh (void)
75 {
76 pthread_mutex_unlock (& simh_lock);
77 }
78 #endif
79
80
81
82 static pthread_mutex_t libuv_lock;
83
84 void lock_libuv (void)
85 {
86 pthread_mutex_lock (& libuv_lock);
87 }
88
89 void unlock_libuv (void)
90 {
91 pthread_mutex_unlock (& libuv_lock);
92 }
93
94 #ifdef TESTING
95 bool test_libuv_lock (void)
96 {
97
98 int rc;
99 rc = pthread_mutex_trylock (& libuv_lock);
100 if (rc)
101 {
102
103 return true;
104 }
105
106 rc = pthread_mutex_unlock (& libuv_lock);
107 if (rc)
108 sim_printf ("test_libuv_lock pthread_mutex_lock libuv_lock %d\n", rc);
109 return false;
110 }
111 #endif
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132 #ifndef LOCKLESS
133 pthread_rwlock_t mem_lock = PTHREAD_RWLOCK_INITIALIZER;
134 static __thread bool have_mem_lock = false;
135 static __thread bool have_rmw_lock = false;
136
137 bool get_rmw_lock (void)
138 {
139 return have_rmw_lock;
140 }
141
142 void lock_rmw (void)
143 {
144 if (have_rmw_lock)
145 {
146 sim_warn ("%s: Already have RMW lock\n", __func__);
147 return;
148 }
149 if (have_mem_lock)
150 {
151 sim_warn ("%s: Already have memory lock\n", __func__);
152 return;
153 }
154 int rc= pthread_rwlock_wrlock (& mem_lock);
155 if (rc)
156 sim_printf ("%s pthread_rwlock_rdlock mem_lock %d\n", __func__, rc);
157 have_mem_lock = true;
158 have_rmw_lock = true;
159 }
160
161 void lock_mem_rd (void)
162 {
163
164 if (have_rmw_lock)
165 return;
166
167 if (have_mem_lock)
168 {
169 sim_warn ("%s: Already have memory lock\n", __func__);
170 return;
171 }
172 int rc= pthread_rwlock_rdlock (& mem_lock);
173 if (rc)
174 sim_printf ("%s pthread_rwlock_rdlock mem_lock %d\n", __func__, rc);
175 have_mem_lock = true;
176 }
177
178 void lock_mem_wr (void)
179 {
180
181 if (have_rmw_lock)
182 return;
183
184 if (have_mem_lock)
185 {
186 sim_warn ("%s: Already have memory lock\n", __func__);
187 return;
188 }
189 int rc= pthread_rwlock_wrlock (& mem_lock);
190 if (rc)
191 sim_printf ("%s pthread_rwlock_wrlock mem_lock %d\n", __func__, rc);
192 have_mem_lock = true;
193 }
194
195 void unlock_rmw (void)
196 {
197 if (! have_mem_lock)
198 {
199 sim_warn ("%s: Don't have memory lock\n", __func__);
200 return;
201 }
202 if (! have_rmw_lock)
203 {
204 sim_warn ("%s: Don't have RMW lock\n", __func__);
205 return;
206 }
207
208 int rc = pthread_rwlock_unlock (& mem_lock);
209 if (rc)
210 sim_printf ("%s pthread_rwlock_ublock mem_lock %d\n", __func__, rc);
211 have_mem_lock = false;
212 have_rmw_lock = false;
213 }
214
215 void unlock_mem (void)
216 {
217 if (have_rmw_lock)
218 return;
219 if (! have_mem_lock)
220 {
221 sim_warn ("%s: Don't have memory lock\n", __func__);
222 return;
223 }
224
225 int rc = pthread_rwlock_unlock (& mem_lock);
226 if (rc)
227 sim_printf ("%s pthread_rwlock_ublock mem_lock %d\n", __func__, rc);
228 have_mem_lock = false;
229 }
230
231 void unlock_mem_force (void)
232 {
233 if (have_mem_lock)
234 {
235 int rc = pthread_rwlock_unlock (& mem_lock);
236 if (rc)
237 sim_printf ("%s pthread_rwlock_unlock mem_lock %d\n", __func__, rc);
238 }
239 have_mem_lock = false;
240 have_rmw_lock = false;
241 }
242 #endif
243
244
245
246 void lock_ptr (pthread_mutex_t * lock)
247 {
248 int rc;
249 rc = pthread_mutex_lock (lock);
250 if (rc)
251 sim_printf ("lock_ptr %d\n", rc);
252 }
253
254 void unlock_ptr (pthread_mutex_t * lock)
255 {
256
257 int rc;
258 rc = pthread_mutex_unlock (lock);
259 if (rc)
260 sim_printf ("unlock_ptr %d\n", rc);
261 }
262
263
264
265 static pthread_mutex_t scu_lock;
266
267 void lock_scu (void)
268 {
269
270 int rc;
271 rc = pthread_mutex_lock (& scu_lock);
272 if (rc)
273 sim_printf ("lock_scu pthread_spin_lock scu %d\n", rc);
274 }
275
276 void unlock_scu (void)
277 {
278
279 int rc;
280 rc = pthread_mutex_unlock (& scu_lock);
281 if (rc)
282 sim_printf ("unlock_scu pthread_spin_lock scu %d\n", rc);
283 }
284
285
286
287 static pthread_mutex_t iom_lock;
288
289 void lock_iom (void)
290 {
291 int rc;
292 rc = pthread_mutex_lock (& iom_lock);
293 if (rc)
294 sim_printf ("%s pthread_spin_lock iom %d\n", __func__, rc);
295 }
296
297 void unlock_iom (void)
298 {
299 int rc;
300 rc = pthread_mutex_unlock (& iom_lock);
301 if (rc)
302 sim_printf ("%s pthread_spin_lock iom %d\n", __func__, rc);
303 }
304
305
306
307 #ifdef TESTING
308 static pthread_mutex_t tst_lock = PTHREAD_MUTEX_INITIALIZER;
309
310 void lock_tst (void)
311 {
312
313 int rc;
314 rc = pthread_mutex_lock (& tst_lock);
315 if (rc)
316 sim_printf ("lock_tst pthread_mutex_lock tst_lock %d\n", rc);
317 }
318
319 void unlock_tst (void)
320 {
321
322 int rc;
323 rc = pthread_mutex_unlock (& tst_lock);
324 if (rc)
325 sim_printf ("unlock_tst pthread_mutex_lock tst_lock %d\n", rc);
326 }
327
328
329
330 bool test_tst_lock (void)
331 {
332
333 int rc;
334 rc = pthread_mutex_trylock (& tst_lock);
335 if (rc)
336 {
337
338 return true;
339 }
340
341 rc = pthread_mutex_unlock (& tst_lock);
342 if (rc)
343 sim_printf ("test_tst_lock pthread_mutex_lock tst_lock %d\n", rc);
344 return false;
345 }
346 #endif
347
348 #ifdef __APPLE__
349
350
351
352
353
354
355 int
356 rtsched_thread(pthread_t pthread)
357 {
358 int kr;
359
360 mach_timebase_info_data_t timebase_info;
361 mach_timebase_info(&timebase_info);
362
363 const uint64_t NANOS_PER_MSEC = 1000000ULL;
364 double mach_clock2abs =
365 ((double)timebase_info.denom / (double)timebase_info.numer) * NANOS_PER_MSEC;
366
367 thread_time_constraint_policy_data_t tpolicy;
368
369 tpolicy.period = 0;
370 tpolicy.computation = (uint32_t)( 5 * mach_clock2abs);
371 tpolicy.constraint = (uint32_t)(10 * mach_clock2abs);
372 tpolicy.preemptible = FALSE;
373
374 mach_port_t target_thread = pthread_mach_thread_np(pthread);
375
376 kr = thread_policy_set(
377 target_thread,
378 THREAD_TIME_CONSTRAINT_POLICY,
379 (thread_policy_t)&tpolicy,
380 THREAD_TIME_CONSTRAINT_POLICY_COUNT);
381
382 if (kr != KERN_SUCCESS)
383 {
384 sim_warn("\rMach thread_policy_set error %d at %s[%s:%d]\r\n",
385 (int)kr, __FILE__, __func__, __LINE__);
386 return 1;
387 }
388
389 # ifdef TESTING
390 sim_warn("\rMach realtime thread scheduling policy request was successful.\r\n");
391 # endif
392 return 0;
393 }
394 #endif
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422 struct cpuThreadz_t cpuThreadz [N_CPU_UNITS_MAX];
423
424
425
426 #if defined(__APPLE__) && !defined(MACOSXPPC)
427 int pthread_create_with_cpu_policy(
428 pthread_t *restrict thread,
429 int policy_group,
430 const pthread_attr_t *restrict attr,
431 void *(*start_routine)(void *), void *restrict arg)
432 {
433 # ifdef TESTING
434 sim_msg ("\rAffinity policy group %d requested for thread.\r\n", policy_group);
435 # endif
436 thread_affinity_policy_data_t policy_data = { policy_group };
437 int rv = pthread_create_suspended_np(thread, attr, start_routine, arg);
438 mach_port_t mach_thread = pthread_mach_thread_np(*thread);
439 if (rv != 0)
440 {
441 return rv;
442 }
443 thread_policy_set(
444 mach_thread,
445 THREAD_AFFINITY_POLICY,
446 (thread_policy_t)&policy_data,
447 THREAD_AFFINITY_POLICY_COUNT);
448 thread_resume(mach_thread);
449 return 0;
450 }
451 #endif
452
453
454
455 void createCPUThread (uint cpuNum)
456 {
457 int rc;
458 struct cpuThreadz_t * p = & cpuThreadz[cpuNum];
459 if (p->run)
460 return;
461 cpu_reset_unit_idx (cpuNum, false);
462 p->cpuThreadArg = (int) cpuNum;
463
464 rc = pthread_mutex_init (& p->runLock, NULL);
465 if (rc)
466 sim_printf ("createCPUThread pthread_mutex_init runLock %d\n", rc);
467 rc = pthread_cond_init (& p->runCond, NULL);
468 if (rc)
469 sim_printf ("createCPUThread pthread_cond_init runCond %d\n", rc);
470
471 p->run = true;
472
473
474 #ifdef USE_MONOTONIC
475 # if defined __APPLE__ || ! defined (CLOCK_MONOTONIC)
476 p->sleepClock = CLOCK_REALTIME;
477 rc = pthread_cond_init (& p->sleepCond, NULL);
478 # else
479 rc = pthread_condattr_init (& p->sleepCondAttr);
480 if (rc)
481 sim_printf ("createCPUThread pthread_condattr_init sleepCond %d\n", rc);
482
483 rc = pthread_condattr_setclock (& p->sleepCondAttr, CLOCK_MONOTONIC);
484 if (rc) {
485
486 p->sleepClock = CLOCK_REALTIME;
487 } else {
488 p->sleepClock = CLOCK_MONOTONIC;
489 }
490 # endif
491 rc = pthread_cond_init (& p->sleepCond, & p->sleepCondAttr);
492 #else
493 rc = pthread_cond_init (& p->sleepCond, NULL);
494 #endif
495 if (rc)
496 sim_printf ("createCPUThread pthread_cond_init sleepCond %d\n", rc);
497
498 #if defined(__APPLE__) && !defined(MACOSXPPC)
499 rc = pthread_create_with_cpu_policy(
500 & p->cpuThread,
501 cpuNum,
502 NULL,
503 cpu_thread_main,
504 & p->cpuThreadArg);
505 #else
506 rc = pthread_create(
507 & p->cpuThread,
508 NULL,
509 cpu_thread_main,
510 & p->cpuThreadArg);
511 #endif
512 if (rc)
513 sim_printf ("createCPUThread pthread_create %d\n", rc);
514
515 char nm [17];
516 sprintf (nm, "CPU %c", 'a' + cpuNum);
517 #ifndef __NetBSD__
518 # if ( defined ( __FreeBSD__ ) || defined ( __OpenBSD__ ) )
519 pthread_set_name_np (p->cpuThread, nm);
520 # else
521 # ifdef __APPLE__
522 # ifndef MACOSXPPC
523 pthread_setname_np (nm);
524 # endif
525 # else
526 # ifndef _AIX
527 # ifndef __gnu_hurd__
528 pthread_setname_np (p->cpuThread, nm);
529 # endif
530 # endif
531 # endif
532 # endif
533 #endif
534
535 #ifdef AFFINITY
536 if (cpus[cpuNum].set_affinity)
537 {
538 cpu_set_t cpuset;
539 CPU_ZERO (& cpuset);
540 CPU_SET (cpus[cpuNum].affinity, & cpuset);
541 int s = pthread_setaffinity_np (p->cpuThread, sizeof (cpu_set_t), & cpuset);
542 if (s)
543 sim_printf ("pthread_setaffinity_np %u on CPU %u returned %d\n",
544 cpus[cpuNum].affinity, cpuNum, s);
545 }
546 #endif
547
548 #ifdef __APPLE__
549 # ifdef USE_RTSCHED_THREAD
550 if (rtsched_thread(p->cpuThread) != 0)
551 sim_printf ("\rrtsched_thread failed %s[%s:%d]!\r\n",
552 __func__, __FILE__, __LINE__);
553 # endif
554 #endif
555 }
556
557 void stopCPUThread(void)
558 {
559 struct cpuThreadz_t * p = & cpuThreadz[current_running_cpu_idx];
560 p->run = false;
561 pthread_exit(NULL);
562 }
563
564
565
566 #ifdef THREADZ
567 void cpuRunningWait (void)
568 {
569 int rc;
570 struct cpuThreadz_t * p = & cpuThreadz[current_running_cpu_idx];
571 if (p->run)
572 return;
573 rc = pthread_mutex_lock (& p->runLock);
574 if (rc)
575 sim_printf ("cpuRunningWait pthread_mutex_lock %d\n", rc);
576 while (! p->run)
577 {
578 rc = pthread_cond_wait (& p->runCond, & p->runLock);
579 if (rc)
580 sim_printf ("cpuRunningWait pthread_cond_wait %d\n", rc);
581 }
582 rc = pthread_mutex_unlock (& p->runLock);
583 if (rc)
584 sim_printf ("cpuRunningWait pthread_mutex_unlock %d\n", rc);
585 }
586 #endif
587
588
589
590 unsigned long sleepCPU (unsigned long usec) {
591 int rc;
592 struct cpuThreadz_t * p = & cpuThreadz[current_running_cpu_idx];
593 struct timespec startTime, absTime;
594
595 #ifdef MACOSXPPC
596 # undef USE_MONOTONIC
597 #endif
598
599 #ifdef USE_MONOTONIC
600 clock_gettime (p->sleepClock, & startTime);
601 #else
602 # ifdef MACOSXPPC
603 clock_serv_t cclock;
604 mach_timespec_t mts;
605 host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
606 clock_get_time(cclock, &mts);
607 mach_port_deallocate(mach_task_self(), cclock);
608 startTime.tv_sec = mts.tv_sec;
609 startTime.tv_nsec = mts.tv_nsec;
610 # else
611 clock_gettime (CLOCK_REALTIME, & startTime);
612 # endif
613 #endif
614 absTime = startTime;
615 int64_t nsec = ((int64_t) usec) * 1000 + (int64_t)startTime.tv_nsec;
616 absTime.tv_nsec = nsec % 1000000000;
617 absTime.tv_sec += nsec / 1000000000;
618
619 rc = pthread_cond_timedwait (& p->sleepCond, & scu_lock, & absTime);
620
621 if (rc == ETIMEDOUT) {
622 return 0;
623 }
624
625 if (rc) {
626 sim_printf ("sleepCPU pthread_cond_timedwait rc %ld usec %ld TR %lu CPU %lu\n", (long) rc, (long) usec, (unsigned long) cpu.rTR, (unsigned long) current_running_cpu_idx);
627 }
628
629 struct timespec newTime;
630 struct timespec delta;
631 #ifdef USE_MONOTONIC
632 clock_gettime (p->sleepClock, & newTime);
633 #else
634 # ifdef MACOSXPPC
635 clock_serv_t ncclock;
636 mach_timespec_t nmts;
637 host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &ncclock);
638 clock_get_time(ncclock, &nmts);
639 mach_port_deallocate(mach_task_self(), ncclock);
640 newTime.tv_sec = nmts.tv_sec;
641 newTime.tv_nsec = nmts.tv_nsec;
642 # else
643 clock_gettime (CLOCK_REALTIME, & newTime);
644 # endif
645 #endif
646 timespec_diff (& absTime, & newTime, & delta);
647
648 if (delta.tv_nsec < 0)
649 return 0;
650 return (unsigned long) delta.tv_nsec / 1000;
651 }
652
653
654
655 void wakeCPU (uint cpuNum)
656 {
657 int rc;
658 struct cpuThreadz_t * p = & cpuThreadz[cpuNum];
659
660 rc = pthread_cond_signal (& p->sleepCond);
661 if (rc)
662 sim_printf ("wakeCPU pthread_cond_signal %d\n", rc);
663 }
664
665 #ifdef IO_THREADZ
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689 struct iomThreadz_t iomThreadz [N_IOM_UNITS_MAX];
690
691
692
693 void createIOMThread (uint iomNum)
694 {
695 int rc;
696 struct iomThreadz_t * p = & iomThreadz[iomNum];
697 # ifdef tdbg
698 p->inCnt = 0;
699 p->outCnt = 0;
700 # endif
701 p->iomThreadArg = (int) iomNum;
702
703 p->ready = false;
704
705 p->intr = false;
706 rc = pthread_mutex_init (& p->intrLock, NULL);
707 if (rc)
708 sim_printf ("createIOMThread pthread_mutex_init intrLock %d\n", rc);
709 rc = pthread_cond_init (& p->intrCond, NULL);
710 if (rc)
711 sim_printf ("createIOMThread pthread_cond_init intrCond %d\n", rc);
712
713 # ifdef __APPLE__
714 rc = pthread_create_with_cpu_policy(
715 & p->iomThread,
716 iomNum,
717 NULL,
718 iom_thread_main,
719 & p->iomThreadArg);
720 # else
721 rc = pthread_create(
722 & p->iomThread,
723 NULL,
724 iom_thread_main,
725 & p->iomThreadArg);
726 # endif
727 if (rc)
728 sim_printf ("createIOMThread pthread_create %d\n", rc);
729
730 char nm [17];
731 sprintf (nm, "IOM %c", 'a' + iomNum);
732 # if ( defined ( __FreeBSD__ ) || defined ( __OpenBSD__ ) )
733 pthread_setname_np (p->iomThread, nm);
734 # else
735 pthread_set_name_np (p->iomThread, nm);
736 # endif
737 }
738
739
740
741 void iomInterruptWait (void)
742 {
743 int rc;
744 struct iomThreadz_t * p = & iomThreadz[this_iom_idx];
745 rc = pthread_mutex_lock (& p->intrLock);
746 if (rc)
747 sim_printf ("iomInterruptWait pthread_mutex_lock %d\n", rc);
748 p -> ready = true;
749 while (! p->intr)
750 {
751 rc = pthread_cond_wait (& p->intrCond, & p->intrLock);
752 if (rc)
753 sim_printf ("iomInterruptWait pthread_cond_wait %d\n", rc);
754 }
755 # ifdef tdbg
756 p->outCnt++;
757 if (p->inCnt != p->outCnt)
758 sim_printf ("iom thread %d in %d out %d\n", this_iom_idx,
759 p->inCnt, p->outCnt);
760 # endif
761 }
762
763
764
765 void iomInterruptDone (void)
766 {
767 int rc;
768 struct iomThreadz_t * p = & iomThreadz[this_iom_idx];
769 p->intr = false;
770 rc = pthread_cond_signal (& p->intrCond);
771 if (rc)
772 sim_printf ("iomInterruptDone pthread_cond_signal %d\n", rc);
773 rc = pthread_mutex_unlock (& p->intrLock);
774 if (rc)
775 sim_printf ("iomInterruptDone pthread_mutex_unlock %d\n", rc);
776 }
777
778
779
780 void iomDoneWait (uint iomNum)
781 {
782 int rc;
783 struct iomThreadz_t * p = & iomThreadz[iomNum];
784 rc = pthread_mutex_lock (& p->intrLock);
785 if (rc)
786 sim_printf ("iomDoneWait pthread_mutex_lock %d\n", rc);
787 while (p->intr)
788 {
789 rc = pthread_cond_wait (& p->intrCond, & p->intrLock);
790 if (rc)
791 sim_printf ("iomDoneWait pthread_cond_wait %d\n", rc);
792 }
793 rc = pthread_mutex_unlock (& p->intrLock);
794 if (rc)
795 sim_printf ("iomDoneWait pthread_mutex_unlock %d\n", rc);
796 }
797
798
799
800 void setIOMInterrupt (uint iomNum)
801 {
802 int rc;
803 struct iomThreadz_t * p = & iomThreadz[iomNum];
804 rc = pthread_mutex_lock (& p->intrLock);
805 if (rc)
806 sim_printf ("setIOMInterrupt pthread_mutex_lock %d\n", rc);
807 while (p->intr)
808 {
809 rc = pthread_cond_wait(&p->intrCond, &p->intrLock);
810 if (rc)
811 sim_printf ("setIOMInterrupt pthread_cond_wait intrLock %d\n", rc);
812 }
813 # ifdef tdbg
814 p->inCnt++;
815 # endif
816 p->intr = true;
817 rc = pthread_cond_signal (& p->intrCond);
818 if (rc)
819 sim_printf ("setIOMInterrupt pthread_cond_signal %d\n", rc);
820 rc = pthread_mutex_unlock (& p->intrLock);
821 if (rc)
822 sim_printf ("setIOMInterrupt pthread_mutex_unlock %d\n", rc);
823 }
824
825
826
827 void iomRdyWait (uint iomNum)
828 {
829 struct iomThreadz_t * p = & iomThreadz[iomNum];
830 while (! p -> ready)
831 sim_usleep (10000);
832 }
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856 struct chnThreadz_t chnThreadz [N_IOM_UNITS_MAX] [MAX_CHANNELS];
857
858
859
860 void createChnThread (uint iomNum, uint chnNum, const char * devTypeStr)
861 {
862 int rc;
863 struct chnThreadz_t * p = & chnThreadz[iomNum][chnNum];
864 p->chnThreadArg = (int) (chnNum + iomNum * MAX_CHANNELS);
865
866 # ifdef tdbg
867 p->inCnt = 0;
868 p->outCnt = 0;
869 # endif
870 p->ready = false;
871
872 p->connect = false;
873 rc = pthread_mutex_init (& p->connectLock, NULL);
874 if (rc)
875 sim_printf ("createChnThread pthread_mutex_init connectLock %d\n", rc);
876 rc = pthread_cond_init (& p->connectCond, NULL);
877 if (rc)
878 sim_printf ("createChnThread pthread_cond_init connectCond %d\n", rc);
879
880 # ifdef __APPLE__
881 rc = pthread_create_with_cpu_policy(
882 & p->chnThread,
883 iomNum
884 NULL,
885 chan_thread_main,
886 & p->chnThreadArg);
887 # else
888 rc = pthread_create(
889 & p->chnThread,
890 NULL,
891 chan_thread_main,
892 & p->chnThreadArg);
893 # endif
894 if (rc)
895 sim_printf ("createChnThread pthread_create %d\n", rc);
896
897 char nm [17];
898 sprintf (nm, "chn %c/%u %s", 'a' + iomNum, chnNum, devTypeStr);
899 # if ( defined ( __FreeBSD__ ) || defined ( __OpenBSD__ ) )
900 pthread_setname_np (p->chnThread, nm);
901 # else
902 pthread_set_name_np (p->chnThread, nm);
903 # endif
904 }
905
906
907
908 void chnConnectWait (void)
909 {
910 int rc;
911 struct chnThreadz_t * p = & chnThreadz[this_iom_idx][this_chan_num];
912
913 rc = pthread_mutex_lock (& p->connectLock);
914 if (rc)
915 sim_printf ("chnConnectWait pthread_mutex_lock %d\n", rc);
916 p -> ready = true;
917 while (! p->connect)
918 {
919 rc = pthread_cond_wait (& p->connectCond, & p->connectLock);
920 if (rc)
921 sim_printf ("chnConnectWait pthread_cond_wait %d\n", rc);
922 }
923 # ifdef tdbg
924 p->outCnt++;
925 if (p->inCnt != p->outCnt)
926 sim_printf ("chn thread %d in %d out %d\n", this_chan_num,
927 p->inCnt, p->outCnt);
928 # endif
929 }
930
931
932
933 void chnConnectDone (void)
934 {
935 int rc;
936 struct chnThreadz_t * p = & chnThreadz[this_iom_idx][this_chan_num];
937 p->connect = false;
938 rc = pthread_cond_signal (& p->connectCond);
939 if (rc)
940 sim_printf ("chnInterruptDone pthread_cond_signal %d\n", rc);
941 rc = pthread_mutex_unlock (& p->connectLock);
942 if (rc)
943 sim_printf ("chnConnectDone pthread_mutex_unlock %d\n", rc);
944 }
945
946
947
948 void setChnConnect (uint iomNum, uint chnNum)
949 {
950 int rc;
951 struct chnThreadz_t * p = & chnThreadz[iomNum][chnNum];
952 rc = pthread_mutex_lock (& p->connectLock);
953 if (rc)
954 sim_printf ("setChnConnect pthread_mutex_lock %d\n", rc);
955 while (p->connect)
956 {
957 rc = pthread_cond_wait(&p->connectCond, &p->connectLock);
958 if (rc)
959 sim_printf ("setChnInterrupt pthread_cond_wait connectLock %d\n", rc);
960 }
961 # ifdef tdbg
962 p->inCnt++;
963 # endif
964 p->connect = true;
965 rc = pthread_cond_signal (& p->connectCond);
966 if (rc)
967 sim_printf ("setChnConnect pthread_cond_signal %d\n", rc);
968 rc = pthread_mutex_unlock (& p->connectLock);
969 if (rc)
970 sim_printf ("setChnConnect pthread_mutex_unlock %d\n", rc);
971 }
972
973
974
975 void chnRdyWait (uint iomNum, uint chnNum)
976 {
977 struct chnThreadz_t * p = & chnThreadz[iomNum][chnNum];
978 while (! p -> ready)
979 sim_usleep (10000);
980 }
981 #endif
982
983 void initThreadz (void)
984 {
985 #ifdef IO_THREADZ
986
987 memset (chnThreadz, 0, sizeof (chnThreadz));
988 #endif
989
990 #ifndef LOCKLESS
991
992 have_mem_lock = false;
993 have_rmw_lock = false;
994 #endif
995 #if ( defined ( __FreeBSD__ ) || defined ( __OpenBSD__ ) )
996 pthread_mutexattr_t scu_attr;
997 pthread_mutexattr_init(&scu_attr);
998 # ifndef __OpenBSD__
999 pthread_mutexattr_settype(&scu_attr, PTHREAD_MUTEX_ADAPTIVE_NP);
1000 # endif
1001 pthread_mutex_init (& scu_lock, &scu_attr);
1002 #else
1003 pthread_mutex_init (& scu_lock, NULL);
1004 #endif
1005 pthread_mutexattr_t iom_attr;
1006 pthread_mutexattr_init(& iom_attr);
1007 pthread_mutexattr_settype(& iom_attr, PTHREAD_MUTEX_RECURSIVE);
1008
1009 pthread_mutex_init (& iom_lock, & iom_attr);
1010
1011 pthread_mutexattr_t libuv_attr;
1012 pthread_mutexattr_init(& libuv_attr);
1013 pthread_mutexattr_settype(& libuv_attr, PTHREAD_MUTEX_RECURSIVE);
1014
1015 pthread_mutex_init (& libuv_lock, & libuv_attr);
1016
1017 #ifdef IO_ASYNC_PAYLOAD_CHAN_THREAD
1018 pthread_cond_init (& iomCond, NULL);
1019 pthread_mutex_init (& iom_start_lock, NULL);
1020 #endif
1021 }
1022
1023
1024
1025 void int_handler (int signal);
1026
1027 void setSignals (void)
1028 {
1029 #ifndef __MINGW64__
1030 # ifndef __MINGW32__
1031 struct sigaction act;
1032 memset (& act, 0, sizeof (act));
1033 act.sa_handler = int_handler;
1034 act.sa_flags = 0;
1035 sigaction (SIGINT, & act, NULL);
1036 sigaction (SIGTERM, & act, NULL);
1037 # endif
1038 #endif
1039 }
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050