unit thr_init; {$mode ObjFPC}{$H+} {$CALLING SysV_ABI_CDecl} interface uses mqueue, syscalls, time, pthread, pthread_md, thr_umtx, thr_private; var _usrstack :Pointer=Pointer($FFFFFFEFFF); //USRSTACK kern.usrstack _thr_initial :p_pthread; _thread_event_mask :Integer; _thread_last_event :p_pthread; _thread_list :pthreadlist=(tqh_first:nil;tqh_last:@_thread_list.tqh_first); _thread_gc_list :pthreadlist=(tqh_first:nil;tqh_last:@_thread_gc_list.tqh_first); _thread_active_threads:Integer=0; _thr_atfork_list :atfork_head=(tqh_first:nil;tqh_last:@_thr_atfork_list.tqh_first); _thr_atfork_lock :urwlock=(rw_state:0;rw_flags:0; rw_blocked_readers:0; rw_blocked_writers:0; rw_spare:(0,0,0,0)); const _thr_priorities :array[0..2] of pthread_prio=( (pri_min:256;pri_max:767;pri_default:700), //FIFO (pri_min:768;pri_max:959;pri_default:900), //OTHER (pri_min:256;pri_max:767;pri_default:700) //RR ); var _pthread_attr_default :pthread_attr=( sched_policy :SCHED_FIFO; sched_inherit :PTHREAD_INHERIT_SCHED; prio :700; suspend :THR_CREATE_RUNNING; flags :PTHREAD_SCOPE_SYSTEM; _align :0; stackaddr_attr:nil; stacksize_attr:$10000; guardsize_attr:0; cpuset :0; cpusetsize :0 ); _pthread_mutexattr_default:pthread_mutex_attr=( m_type :PTHREAD_MUTEX_DEFAULT; m_protocol:PTHREAD_PRIO_NONE; m_ceiling :0 ); _pthread_mutexattr_adaptive_default:pthread_mutex_attr=( m_type :PTHREAD_MUTEX_ADAPTIVE; m_protocol:PTHREAD_PRIO_NONE; m_ceiling :0 ); _pthread_condattr_default:pthread_cond_attr=( c_pshared:PTHREAD_PROCESS_PRIVATE; c_clockid:CLOCK_REALTIME; ); _thr_pid:Integer; _thr_is_smp :Integer=1; //kern.smp.cpus _thr_guard_default :Integer; _thr_stack_default :QWORD =THR_STACK_DEFAULT; _thr_stack_initial :QWORD =THR_STACK_INITIAL; _thr_page_size :Integer=4*1024; //getpagesize _thr_spinloops :Integer; _thr_yieldloops:Integer; _gc_count :Integer; _mutex_static_lock :umutex= (m_owner:0;m_flags:0;m_ceilings:(0,0);m_spare:(0,0)); _cond_static_lock :umutex= (m_owner:0;m_flags:0;m_ceilings:(0,0);m_spare:(0,0)); _rwlock_static_lock:umutex= (m_owner:0;m_flags:0;m_ceilings:(0,0);m_spare:(0,0)); _keytable_lock :umutex= (m_owner:0;m_flags:0;m_ceilings:(0,0);m_spare:(0,0)); _thr_list_lock :urwlock=(rw_state:0;rw_flags:0; rw_blocked_readers:0; rw_blocked_writers:0; rw_spare:(0,0,0,0)); _thr_event_lock :umutex= (m_owner:0;m_flags:0;m_ceilings:(0,0);m_spare:(0,0)); init_once:Integer=0; procedure _libpthread_init(curthread:p_pthread); implementation uses sys_mmap; const g_user_stacksize=$10000; procedure init_private; begin _thr_umutex_init(@_mutex_static_lock); _thr_umutex_init(@_cond_static_lock); _thr_umutex_init(@_rwlock_static_lock); _thr_umutex_init(@_keytable_lock); _thr_urwlock_init(@_thr_atfork_lock); _thr_umutex_init(@_thr_event_lock); //_thr_once_init(); //_thr_spinlock_init(); //_thr_list_init(); //_thr_wake_addr_init(); //_sleepq_init(); if (init_once=0) then begin //mib[0]:=1; //mib[1]:=33; //len:=8; //ret:=sysctl(mib,2,@_usrstack,@len,nil,0); //if (ret=-1) then //begin // Assert(false,'Cannot get kern.usrstack from sysctl'); //end; //len:=4; //sysctlbyname('kern.smp.cpus',@_thr_is_smp,@len,0,0); //_thr_is_smp:=(1<_thr_is_smp); //_thr_page_size:=getpagesize(); _pthread_attr_default.guardsize_attr:=_thr_page_size; _thr_guard_default:=_pthread_attr_default.guardsize_attr; //ret:=IsSystemProcess(getpid()); _thr_atfork_list.tqh_first:=nil; _pthread_attr_default.stacksize_attr:=$200000; //if (ret<>1) then begin _pthread_attr_default.stacksize_attr:=g_user_stacksize; end; end; init_once:=1; end; procedure init_main_thread(thread:p_pthread); var ret:Pointer; param:sched_param; begin thr_self(@thread^.tid); thread^.attr:=_pthread_attr_default; ret:=mmap(_usrstack-_thr_guard_default-_thr_stack_initial,_thr_guard_default,0,MAP_ANON,-1,0); if (ret=MAP_FAILED) then begin Assert(false,'Cannot allocate red zone for initial thread'); Exit; end; thread^.attr.stackaddr_attr:=(_usrstack-_thr_stack_initial); thread^.attr.stacksize_attr:=_thr_stack_initial; thread^.attr.guardsize_attr:=_thr_guard_default; thread^.attr.flags:=thread^.attr.flags or THR_STACK_USER; thread^.magic:=THR_MAGIC; thread^.cancel_enable:=1; thread^.cancel_async:=0; TAILQ_INIT(@thread^.mutexq); TAILQ_INIT(@thread^.pp_mutexq); thread^.state:=PS_RUNNING; param:=Default(sched_param); //_thr_getscheduler(thread^.tid,@thread^.attr.sched_policy,@param); thread^.attr.prio:=param.sched_priority; thread^.unwind_stackend:=_usrstack; end; procedure _libpthread_init(curthread:p_pthread); var first:Integer; begin if (_thr_initial<>nil) and (curthread=nil) then Exit; _thr_pid:=getpid(); init_private; first:=0; if (curthread=nil) then begin //curthread:=_thr_alloc(nil); if (curthread=nil) then begin Assert(false,'Can''t allocate initial thread'); end; init_main_thread(curthread); first:=1; end; THR_LIST_ADD(curthread); _thread_active_threads:=1; if (first<>0) then begin _thr_initial:=curthread; _tcb_set(curthread^.tcb); end; end; end.