freebsd.pas 11 KB

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