freebsd.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. {$IFNDEF FPC_DOTTEDUNITS}
  2. Unit FreeBSD;
  3. {$ENDIF FPC_DOTTEDUNITS}
  4. {
  5. This file is part of the Free Pascal run time library.
  6. (c) 2005 by Marco van de Voort
  7. member of the Free Pascal development team.
  8. based on the sendfile conversion of Ales Katona 30.01.2006
  9. See the file COPYING.FPC, included in this distribution,
  10. for details about the copyright.
  11. Unit for FreeBSD specific calls. Calls may move to "BSD" unit in time,
  12. if turns out that more BSDs include them.
  13. This program is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY;without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  16. }
  17. {$IFDEF FPC}
  18. {$PACKRECORDS C}
  19. {$inline on}
  20. {$Macro On}
  21. {$ifdef FPC_USE_LIBC}
  22. {$define extdecl:=cdecl; external 'c'}
  23. {$else}
  24. {$define extdecl:=inline}
  25. {$endif}
  26. {$ENDIF}
  27. interface
  28. {$IFDEF FPC_DOTTEDUNITS}
  29. uses
  30. UnixApi.Base;
  31. {$ELSE FPC_DOTTEDUNITS}
  32. uses
  33. BaseUnix;
  34. {$ENDIF FPC_DOTTEDUNITS}
  35. const
  36. SF_NODISKIO = $00000001; // don't wait for disk IO, similar to non-blocking socket setting
  37. // kernel threads
  38. KSE_VER_0 = 0;
  39. KSE_VERSION = KSE_VER_0;
  40. {* These flags are kept in km_flags *}
  41. KMF_NOUPCALL = $01;
  42. KMF_NOCOMPLETED = $02;
  43. KMF_DONE = $04;
  44. KMF_BOUND = $08;
  45. KMF_WAITSIGEVENT = $10;
  46. {* These flags are kept in tm_flags *}
  47. TMF_NOUPCALL = $01;
  48. {* These flags are kept in tm_dlfags *}
  49. TMDF_SSTEP = $01;
  50. TMDF_SUSPEND = $02;
  51. {* Flags for kse_switchin *}
  52. KSE_SWITCHIN_SETTMBX = $01;
  53. {* Commands for kse_thr_interrupt *}
  54. KSE_INTR_INTERRUPT = 1;
  55. KSE_INTR_RESTART = 2;
  56. KSE_INTR_SENDSIG = 3;
  57. KSE_INTR_SIGEXIT = 4;
  58. KSE_INTR_DBSUSPEND = 5;
  59. KSE_INTR_EXECVE = 6;
  60. {$i ucontexth.inc} // required for kse threads
  61. Type
  62. SF_HDTR = record
  63. headers: PIOVec; {* pointer to an array of header struct iovec's *}
  64. hdr_cnt: cint; {* number of header iovec's *}
  65. trailers: PIOVec; {* pointer to an array of trailer struct iovec's *}
  66. trl_cnt: cint; {* number of trailer iovec's *}
  67. end;
  68. TSF_HDTR = SF_HDTR;
  69. PSF_HDTR = ^TSF_HDTR;
  70. kld_file_stat = record
  71. Version: cInt; {* set to sizeof(linker_file_stat) *}
  72. Name: array[0..MAXPATHLEN-1] of AnsiChar;
  73. Refs: cInt;
  74. ID: cInt;
  75. Address: PAnsiChar; {* load address *}
  76. Size: size_t; {* size in bytes *}
  77. end;
  78. tkld_file_stat = kld_file_stat;
  79. pkld_file_stat = ^kld_file_stat;
  80. TKldFileStat = kld_file_stat;
  81. PKldFileStat = ^kld_file_stat;
  82. kld_sym_lookup = record
  83. Version: cInt; {* sizeof(struct kld_sym_lookup) *}
  84. SymName: PAnsiChar; {* Symbol name we are looking up *}
  85. SymValue: culong;
  86. SymSize: size_t;
  87. end;
  88. tkld_sym_lookup = kld_sym_lookup;
  89. pkld_sym_lookup = ^kld_sym_lookup;
  90. TKldSymLookup = kld_sym_lookup;
  91. PKldSymLookup = ^kld_sym_lookup;
  92. // kernel threads
  93. pkse_mailbox = ^kse_mailbox;
  94. pkse_func_t = ^kse_func_t;
  95. kse_func_t = procedure(mbx: pkse_mailbox);
  96. TKseFunc = kse_func_t;
  97. PKseFunc = pkse_func_t;
  98. {*
  99. * Thread mailbox.
  100. *
  101. * This describes a user thread to the kernel scheduler.
  102. *}
  103. pkse_thr_mailbox = ^kse_thr_mailbox;
  104. kse_thr_mailbox = record
  105. tm_context: ucontext_t; {* User and machine context *}
  106. tm_flags: cuint32; {* Thread flags *}
  107. tm_next: pkse_thr_mailbox; {* Next thread in list *}
  108. tm_udata: Pointer; {* For use by the UTS *}
  109. tm_uticks: cuint32; {* Time in userland *}
  110. tm_sticks: cuint32; {* Time in kernel *}
  111. tm_syncsig: siginfo_t;
  112. tm_dflags: cuint32; {* Debug flags *}
  113. tm_lwp: lwpid_t; {* kernel thread UTS runs on *}
  114. __spare__: array [0..5] of cuint32;
  115. end;
  116. TKseThrMailBox = kse_thr_mailbox;
  117. PKseThrMailBox = pkse_thr_mailbox;
  118. {*
  119. * KSE mailbox.
  120. *
  121. * Communication path between the UTS and the kernel scheduler specific to
  122. * a single KSE.
  123. *}
  124. kse_mailbox = record
  125. km_version: cuint32; {* Mailbox version *}
  126. km_curthread: pkse_thr_mailbox; {* Currently running thread *}
  127. km_completed: pkse_thr_mailbox; {* Threads back from kernel *}
  128. km_sigscaught: sigset_t; {* Caught signals *}
  129. km_flags: cuint32; {* Mailbox flags *}
  130. km_func: pkse_func_t; {* UTS function *}
  131. km_stack: stack_t; {* UTS stack *}
  132. km_udata: Pointer; {* For use by the UTS *}
  133. km_timeofday: TTimeSpec; {* Time of day *}
  134. km_quantum: cuint32; {* Upcall quantum in msecs *}
  135. km_lwp: lwpid_t; {* kernel thread UTS runs on *}
  136. __spare2__: array[0..6] of cuint32
  137. end;
  138. TKseMailBox = kse_mailbox;
  139. PKseMailBox = pkse_mailbox;
  140. function sendfile(fd: cint; s: cint; Offset: TOff; nBytes: TSize;
  141. HDTR: PSF_HDTR; sBytes: POff; Flags: cint): cint; extdecl;
  142. // Kernel modules support
  143. function kldload(FileName: PAnsiChar): cInt; extdecl;
  144. function kldunload(fileid: cInt): cInt; extdecl;
  145. function kldfind(FileName: PAnsiChar): cInt; extdecl;
  146. function kldnext(fileid: cInt): cInt; extdecl;
  147. function kldstat(fileid: cInt; kld_file_stat: pKldFileStat): cInt; extdecl;
  148. function kldfirstmod(fileid: cInt): cInt; extdecl;
  149. function kldsym(fileid: cInt; command: cInt; data: PKldSymLookup): cInt; extdecl;
  150. // kernel threads support
  151. function kse_exit: cInt; extdecl;
  152. function kse_wakeup(mbx: PKseMailBox): cInt; extdecl;
  153. function kse_create(mbx: PKseMailBox; newgroup: cInt): cInt; extdecl;
  154. function kse_thr_interrupt(tmbx: PKseThrMailBox; cmd: cInt; data: cLong): cInt; extdecl;
  155. function kse_release(timeout: PTimeSpec): cInt; extdecl;
  156. function kse_switchin(tmbx: PKseThrMailBox; flags: cInt): cInt; extdecl;
  157. {$ifndef FPC_USE_LIBC}
  158. function fpgetfsstat(buf:pstatfs;bufsize:clong;flags:cint):cint;
  159. {$endif}
  160. Const
  161. MAP_FILE = $0000; { map from file (default) }
  162. MAP_ANON = $1000; { allocated from memory, swap space }
  163. MAP_RENAME = $0020; { Sun: rename private pages to file }
  164. MAP_NORESERVE = $0040; { Sun: don't reserve needed swap area }
  165. // MAP_INHERIT = $0080; { region is retained after exec. not anymore in 5.x? }
  166. // MAP_NOEXTEND = $0100; { for MAP_FILE, don't change file size. not anymore in 5.x? }
  167. MAP_HASSEMAPHORE = $0200; { region may contain semaphores }
  168. MAP_STACK = $0400; { region grows down, like a stack }
  169. MAP_NOSYNC = $0800; { page to but do not sync underlying file}
  170. MAP_NOCORE = $20000;{ dont include these pages in a coredump}
  171. function kernproc_getgenvalue(pid:pid_t;kernproc_variable:cint;var s:ansistring):cint;
  172. function kernproc_getargs(pid:pid_t;var fn:ansistring):cint;
  173. function kernproc_getpath(pid:pid_t;var fn:ansistring):cint;
  174. // Taken from /usr/include/time.h
  175. const
  176. CLOCK_REALTIME = 0;
  177. CLOCK_VIRTUAL = 1;
  178. CLOCK_PROF = 2;
  179. CLOCK_MONOTONIC = 4;
  180. // FreeBSD specific
  181. CLOCK_UPTIME = 5;
  182. CLOCK_UPTIME_PRECISE = 7;
  183. CLOCK_UPTIME_FAST = 8;
  184. CLOCK_REALTIME_PRECISE = 9;
  185. CLOCK_REALTIME_FAST = 10;
  186. CLOCK_MONOTONIC_PRECISE = 11;
  187. CLOCK_MONOTONIC_FAST = 12;
  188. CLOCK_SECOND = 13;
  189. CLOCK_THREAD_CPUTIME_ID = 14;
  190. CLOCK_PROCESS_CPUTIME_ID = 15;
  191. Type
  192. clockid_t = cint;
  193. function clock_getres(clk_id: clockid_t; res: ptimespec): cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'clock_getres'; {$ENDIF}
  194. function clock_gettime(clk_id: clockid_t; tp: ptimespec): cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'clock_gettime'; {$ENDIF}
  195. function clock_settime(clk_id: clockid_t; tp: ptimespec): cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'clock_settime'; {$ENDIF}
  196. implementation
  197. {$IFDEF FPC_DOTTEDUNITS}
  198. Uses BsdApi.SysCtl,
  199. {$ifndef FPC_USE_LIBC} UnixApi.SysCall; {$else} System.InitC; {$endif}
  200. {$ELSE FPC_DOTTEDUNITS}
  201. Uses Sysctl,
  202. {$ifndef FPC_USE_LIBC} SysCall; {$else} InitC; {$endif}
  203. {$ENDIF FPC_DOTTEDUNITS}
  204. {$IFNDEF FPC_USE_LIBC}
  205. function SendFile(fd: cint; s: cint; Offset: TOff; nBytes: TSize;
  206. HDTR: PSF_HDTR; sBytes: POff; Flags: cint): cint;
  207. begin
  208. SendFile:=Do_Syscall(syscall_nr_sendfile, fd, s,
  209. {$IFNDEF CPU64}
  210. {$IFDEF LITTLE_ENDIAN} // little endian is lo - hi
  211. Lo(Offset), Hi(Offset),
  212. {$ELSE} // big endian is hi - lo
  213. Hi(Offset), Lo(Offset),
  214. {$ENDIF}
  215. {$ELSE} // 64-bit doesn't care.
  216. TSysParam(Offset),
  217. {$ENDIF}
  218. nBytes, TSysParam(HDTR), TSysParam(sBytes), Flags);
  219. end;
  220. // kernel modules
  221. function kldload(FileName: PAnsiChar): cInt;
  222. begin
  223. kldload:=do_sysCall(syscall_nr_kldload, TSysParam(FileName));
  224. end;
  225. function kldunload(fileid: cInt): cInt;
  226. begin
  227. kldunload:=do_sysCall(syscall_nr_kldunload, TSysParam(fileid));
  228. end;
  229. function kldfind(FileName: PAnsiChar): cInt;
  230. begin
  231. kldfind:=do_sysCall(syscall_nr_kldfind, TSysParam(FileName));
  232. end;
  233. function kldnext(fileid: cInt): cInt;
  234. begin
  235. kldnext:=do_sysCall(syscall_nr_kldnext, TSysParam(fileid));
  236. end;
  237. function kldstat(fileid: cInt; kld_file_stat: pKldFileStat): cInt;
  238. begin
  239. kldstat:=do_sysCall(syscall_nr_kldstat, TSysParam(fileid),
  240. TSysParam(kld_file_stat));
  241. end;
  242. function kldfirstmod(fileid: cInt): cInt;
  243. begin
  244. kldfirstmod:=do_sysCall(syscall_nr_kldfirstmod, TSysParam(fileid));
  245. end;
  246. function kldsym(fileid: cInt; command: cInt; data: PKldSymLookup): cInt;
  247. begin
  248. kldsym:=do_sysCall(syscall_nr_kldsym, TSysParam(fileid), TSysParam(command),
  249. TSysParam(data));
  250. end;
  251. // kernel threads
  252. function kse_exit: cInt;
  253. begin
  254. kse_exit:=do_sysCall(TSysParam(syscall_nr_kse_exit));
  255. end;
  256. function kse_wakeup(mbx: PKseMailBox): cInt;
  257. begin
  258. kse_wakeup:=do_sysCall(syscall_nr_kse_wakeup, TSysParam(mbx));
  259. end;
  260. function kse_create(mbx: PKseMailBox; newgroup: cInt): cInt;
  261. begin
  262. kse_create:=do_sysCall(syscall_nr_kse_create, TSysParam(mbx),
  263. TSysParam(newgroup));
  264. end;
  265. function kse_thr_interrupt(tmbx: PKseThrMailBox; cmd: cInt; data: cLong): cInt;
  266. begin
  267. kse_thr_interrupt:=do_SysCall(syscall_nr_kse_thr_interrupt, TSysParam(tmbx),
  268. TSysParam(cmd), TSysParam(data));
  269. end;
  270. function kse_release(timeout: PTimeSpec): cInt;
  271. begin
  272. kse_release:=do_SysCall(syscall_nr_kse_release, TSysParam(timeout));
  273. end;
  274. function kse_switchin(tmbx: PKseThrMailBox; flags: cInt): cInt;
  275. begin
  276. kse_switchin:=do_SysCall(syscall_nr_kse_switchin, TSysParam(tmbx), TSysParam(flags));
  277. end;
  278. function fpgetfsstat(buf:pstatfs;bufsize:clong;flags:cint):cint;
  279. begin
  280. fpgetfsstat:=do_syscall(syscall_nr_getfsstat,TSysParam(buf),TSysParam(Bufsize),TSysParam(Flags));
  281. end;
  282. function clock_getres(clk_id: clockid_t; res: ptimespec): cint;
  283. begin
  284. clock_getres := do_SysCall(syscall_nr_clock_getres,tsysparam(clk_id),tsysparam(res));
  285. end;
  286. function clock_gettime(clk_id: clockid_t; tp: ptimespec): cint;
  287. begin
  288. clock_gettime := do_SysCall(syscall_nr_clock_gettime,tsysparam(clk_id),tsysparam(tp));
  289. end;
  290. function clock_settime(clk_id: clockid_t; tp: ptimespec): cint;
  291. begin
  292. clock_settime := do_SysCall(syscall_nr_clock_settime,tsysparam(clk_id),tsysparam(tp));
  293. end;
  294. {$ENDIF}
  295. function kernproc_getgenvalue(pid:pid_t;kernproc_variable:cint;var s:ansistring):cint;
  296. var mib: array[0..3] of cint;
  297. argv_len : size_t;
  298. ret:cint;
  299. Begin
  300. mib[0]:=CTL_KERN;
  301. mib[1]:=kern_proc;
  302. Mib[2]:=kernproc_variable;
  303. Mib[3]:=pid;
  304. setlength(s,arg_max);
  305. argv_len:=ARG_MAX;
  306. ret:=fpsysctl(@mib, high(mib)+1, @s[1], @argv_len, NIL, 0);
  307. if ret<>-1 then
  308. setlength(s,argv_len)
  309. else
  310. setlength(s,0);
  311. kernproc_getgenvalue:=ret;
  312. end;
  313. function kernproc_getargs(pid:pid_t;var fn:ansistring):cint;
  314. begin
  315. kernproc_getargs:=kernproc_getgenvalue(pid,KERN_PROC_ARGS,fn);
  316. end;
  317. function kernproc_getpath(pid:pid_t;var fn:ansistring):cint;
  318. begin
  319. kernproc_getpath:=kernproc_getgenvalue(pid,KERN_PROC_PATHNAME,fn);
  320. end;
  321. end.