1/*
2 * Copyright 2004-2019, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef _OS_H
6#define _OS_H
7
8/** Kernel specific structures and functions */
9
10#include <limits.h>
11#include <stdarg.h>
12#include <sys/types.h>
13
14#include <SupportDefs.h>
15#include <StorageDefs.h>
16
17
18#ifdef __cplusplus
19extern "C" {
20#endif
21
22/* System constants */
23
24#define B_OS_NAME_LENGTH	32
25#define B_INFINITE_TIMEOUT	(9223372036854775807LL)
26
27#define B_PAGE_SIZE			PAGESIZE
28
29enum {
30	B_TIMEOUT						= 0x8,	/* relative timeout */
31	B_RELATIVE_TIMEOUT				= 0x8,	/* fails after a relative timeout
32												with B_TIMED_OUT */
33	B_ABSOLUTE_TIMEOUT				= 0x10,	/* fails after an absolute timeout
34												with B_TIMED_OUT */
35
36	/* experimental Haiku only API */
37	B_TIMEOUT_REAL_TIME_BASE		= 0x40,
38	B_ABSOLUTE_REAL_TIME_TIMEOUT	= B_ABSOLUTE_TIMEOUT
39										| B_TIMEOUT_REAL_TIME_BASE
40};
41
42
43/* Types */
44
45typedef int32 area_id;
46typedef int32 port_id;
47typedef int32 sem_id;
48typedef int32 team_id;
49typedef int32 thread_id;
50
51
52/* Areas */
53
54typedef struct area_info {
55	area_id		area;
56	char		name[B_OS_NAME_LENGTH];
57	size_t		size;
58	uint32		lock;
59	uint32		protection;
60	team_id		team;
61	uint32		ram_size;
62	uint32		copy_count;
63	uint32		in_count;
64	uint32		out_count;
65	void		*address;
66} area_info;
67
68/* area locking */
69#define B_NO_LOCK				0
70#define B_LAZY_LOCK				1
71#define B_FULL_LOCK				2
72#define B_CONTIGUOUS			3
73#define	B_LOMEM					4	/* B_CONTIGUOUS, < 16 MB physical address */
74#define	B_32_BIT_FULL_LOCK		5	/* B_FULL_LOCK, < 4 GB physical addresses */
75#define	B_32_BIT_CONTIGUOUS		6	/* B_CONTIGUOUS, < 4 GB physical address */
76
77/* address spec for create_area(), and clone_area() */
78#define B_ANY_ADDRESS				0
79#define B_EXACT_ADDRESS				1
80#define B_BASE_ADDRESS				2
81#define B_CLONE_ADDRESS				3
82#define	B_ANY_KERNEL_ADDRESS		4
83/* B_ANY_KERNEL_BLOCK_ADDRESS		5 */
84#define B_RANDOMIZED_ANY_ADDRESS	6
85#define B_RANDOMIZED_BASE_ADDRESS	7
86
87/* area protection */
88#define B_READ_AREA				(1 << 0)
89#define B_WRITE_AREA			(1 << 1)
90#define B_EXECUTE_AREA			(1 << 2)
91#define B_STACK_AREA			(1 << 3)
92	/* "stack" protection is not available on most platforms - it's used
93	   to only commit memory as needed, and have guard pages at the
94	   bottom of the stack. */
95#define B_CLONEABLE_AREA		(1 << 8)
96
97extern area_id		create_area(const char *name, void **startAddress,
98						uint32 addressSpec, size_t size, uint32 lock,
99						uint32 protection);
100extern area_id		clone_area(const char *name, void **destAddress,
101						uint32 addressSpec, uint32 protection, area_id source);
102extern area_id		find_area(const char *name);
103extern area_id		area_for(void *address);
104extern status_t		delete_area(area_id id);
105extern status_t		resize_area(area_id id, size_t newSize);
106extern status_t		set_area_protection(area_id id, uint32 newProtection);
107
108/* system private, use macros instead */
109extern status_t		_get_area_info(area_id id, area_info *areaInfo, size_t size);
110extern status_t		_get_next_area_info(team_id team, ssize_t *cookie,
111						area_info *areaInfo, size_t size);
112
113#define get_area_info(id, areaInfo) \
114	_get_area_info((id), (areaInfo),sizeof(*(areaInfo)))
115#define get_next_area_info(team, cookie, areaInfo) \
116	_get_next_area_info((team), (cookie), (areaInfo), sizeof(*(areaInfo)))
117
118
119/* Ports */
120
121typedef struct port_info {
122	port_id		port;
123	team_id		team;
124	char		name[B_OS_NAME_LENGTH];
125	int32		capacity;		/* queue depth */
126	int32		queue_count;	/* # msgs waiting to be read */
127	int32		total_count;	/* total # msgs read so far */
128} port_info;
129
130extern port_id		create_port(int32 capacity, const char *name);
131extern port_id		find_port(const char *name);
132extern ssize_t		read_port(port_id port, int32 *code, void *buffer,
133						size_t bufferSize);
134extern ssize_t		read_port_etc(port_id port, int32 *code, void *buffer,
135						size_t bufferSize, uint32 flags, bigtime_t timeout);
136extern status_t		write_port(port_id port, int32 code, const void *buffer,
137						size_t bufferSize);
138extern status_t		write_port_etc(port_id port, int32 code, const void *buffer,
139						size_t bufferSize, uint32 flags, bigtime_t timeout);
140extern status_t		close_port(port_id port);
141extern status_t		delete_port(port_id port);
142
143extern ssize_t		port_buffer_size(port_id port);
144extern ssize_t		port_buffer_size_etc(port_id port, uint32 flags,
145						bigtime_t timeout);
146extern ssize_t		port_count(port_id port);
147extern status_t		set_port_owner(port_id port, team_id team);
148
149/* system private, use the macros instead */
150extern status_t		_get_port_info(port_id port, port_info *portInfo,
151						size_t portInfoSize);
152extern status_t		_get_next_port_info(team_id team, int32 *cookie,
153						port_info *portInfo, size_t portInfoSize);
154
155#define get_port_info(port, info) \
156	_get_port_info((port), (info), sizeof(*(info)))
157#define get_next_port_info(team, cookie, info) \
158	_get_next_port_info((team), (cookie), (info), sizeof(*(info)))
159
160
161/* WARNING: The following is Haiku experimental API. It might be removed or
162   changed in the future. */
163
164typedef struct port_message_info {
165	size_t		size;
166	uid_t		sender;
167	gid_t		sender_group;
168	team_id		sender_team;
169} port_message_info;
170
171/* similar to port_buffer_size_etc(), but returns (more) info */
172extern status_t		_get_port_message_info_etc(port_id port,
173						port_message_info *info, size_t infoSize, uint32 flags,
174						bigtime_t timeout);
175
176#define get_port_message_info_etc(port, info, flags, timeout) \
177	_get_port_message_info_etc((port), (info), sizeof(*(info)), flags, timeout)
178
179
180/* Semaphores */
181
182typedef struct sem_info {
183	sem_id		sem;
184	team_id		team;
185	char		name[B_OS_NAME_LENGTH];
186	int32		count;
187	thread_id	latest_holder;
188} sem_info;
189
190/* semaphore flags */
191enum {
192	B_CAN_INTERRUPT				= 0x01,	/* acquisition of the semaphore can be
193										   interrupted (system use only) */
194	B_CHECK_PERMISSION			= 0x04,	/* ownership will be checked (system use
195										   only) */
196	B_KILL_CAN_INTERRUPT		= 0x20,	/* acquisition of the semaphore can be
197										   interrupted by SIGKILL[THR], even
198										   if not B_CAN_INTERRUPT (system use
199										   only) */
200
201	/* release_sem_etc() only flags */
202	B_DO_NOT_RESCHEDULE			= 0x02,	/* thread is not rescheduled */
203	B_RELEASE_ALL				= 0x08,	/* all waiting threads will be woken up,
204										   count will be zeroed */
205	B_RELEASE_IF_WAITING_ONLY	= 0x10	/* release count only if there are any
206										   threads waiting */
207};
208
209extern sem_id		create_sem(int32 count, const char *name);
210extern status_t		delete_sem(sem_id id);
211extern status_t		acquire_sem(sem_id id);
212extern status_t		acquire_sem_etc(sem_id id, int32 count, uint32 flags,
213						bigtime_t timeout);
214extern status_t		release_sem(sem_id id);
215extern status_t		release_sem_etc(sem_id id, int32 count, uint32 flags);
216/* TODO: the following two calls are not part of the BeOS API, and might be
217   changed or even removed for the final release of Haiku R1 */
218extern status_t		switch_sem(sem_id semToBeReleased, sem_id id);
219extern status_t		switch_sem_etc(sem_id semToBeReleased, sem_id id,
220						int32 count, uint32 flags, bigtime_t timeout);
221extern status_t		get_sem_count(sem_id id, int32 *threadCount);
222extern status_t		set_sem_owner(sem_id id, team_id team);
223
224/* system private, use the macros instead */
225extern status_t		_get_sem_info(sem_id id, struct sem_info *info,
226						size_t infoSize);
227extern status_t		_get_next_sem_info(team_id team, int32 *cookie,
228						struct sem_info *info, size_t infoSize);
229
230#define get_sem_info(sem, info) \
231	_get_sem_info((sem), (info), sizeof(*(info)))
232
233#define get_next_sem_info(team, cookie, info) \
234	_get_next_sem_info((team), (cookie), (info), sizeof(*(info)))
235
236
237/* Teams */
238
239typedef struct {
240	team_id			team;
241	int32			thread_count;
242	int32			image_count;
243	int32			area_count;
244	thread_id		debugger_nub_thread;
245	port_id			debugger_nub_port;
246	int32			argc;
247	char			args[64];
248	uid_t			uid;
249	gid_t			gid;
250
251	/* Haiku R1 extensions */
252	uid_t			real_uid;
253	gid_t			real_gid;
254	pid_t			group_id;
255	pid_t			session_id;
256	team_id			parent;
257	char			name[B_OS_NAME_LENGTH];
258	bigtime_t		start_time;
259} team_info;
260
261#define B_CURRENT_TEAM	0
262#define B_SYSTEM_TEAM	1
263
264extern status_t		kill_team(team_id team);
265	/* see also: send_signal() */
266
267/* system private, use macros instead */
268extern status_t		_get_team_info(team_id id, team_info *info, size_t size);
269extern status_t		_get_next_team_info(int32 *cookie, team_info *info,
270						size_t size);
271
272#define get_team_info(id, info) \
273	_get_team_info((id), (info), sizeof(*(info)))
274
275#define get_next_team_info(cookie, info) \
276	_get_next_team_info((cookie), (info), sizeof(*(info)))
277
278/* team usage info */
279
280typedef struct {
281	bigtime_t		user_time;
282	bigtime_t		kernel_time;
283} team_usage_info;
284
285enum {
286	/* compatible to sys/resource.h RUSAGE_SELF and RUSAGE_CHILDREN */
287	B_TEAM_USAGE_SELF		= 0,
288	B_TEAM_USAGE_CHILDREN	= -1
289};
290
291/* system private, use macros instead */
292extern status_t		_get_team_usage_info(team_id team, int32 who,
293						team_usage_info *info, size_t size);
294
295#define get_team_usage_info(team, who, info) \
296	_get_team_usage_info((team), (who), (info), sizeof(*(info)))
297
298
299/* Threads */
300
301typedef enum {
302	B_THREAD_RUNNING	= 1,
303	B_THREAD_READY,
304	B_THREAD_RECEIVING,
305	B_THREAD_ASLEEP,
306	B_THREAD_SUSPENDED,
307	B_THREAD_WAITING
308} thread_state;
309
310typedef struct {
311	thread_id		thread;
312	team_id			team;
313	char			name[B_OS_NAME_LENGTH];
314	thread_state	state;
315	int32			priority;
316	sem_id			sem;
317	bigtime_t		user_time;
318	bigtime_t		kernel_time;
319	void			*stack_base;
320	void			*stack_end;
321} thread_info;
322
323#define B_IDLE_PRIORITY					0
324#define B_LOWEST_ACTIVE_PRIORITY		1
325#define B_LOW_PRIORITY					5
326#define B_NORMAL_PRIORITY				10
327#define B_DISPLAY_PRIORITY				15
328#define	B_URGENT_DISPLAY_PRIORITY		20
329#define	B_REAL_TIME_DISPLAY_PRIORITY	100
330#define	B_URGENT_PRIORITY				110
331#define B_REAL_TIME_PRIORITY			120
332
333#define B_SYSTEM_TIMEBASE				0
334	/* time base for snooze_*(), compatible with the clockid_t constants defined
335	   in <time.h> */
336
337#define B_FIRST_REAL_TIME_PRIORITY		B_REAL_TIME_DISPLAY_PRIORITY
338
339typedef status_t (*thread_func)(void *);
340#define thread_entry thread_func
341	/* thread_entry is for backward compatibility only! Use thread_func */
342
343extern thread_id	spawn_thread(thread_func, const char *name, int32 priority,
344						void *data);
345extern status_t		kill_thread(thread_id thread);
346extern status_t		resume_thread(thread_id thread);
347extern status_t		suspend_thread(thread_id thread);
348
349extern status_t		rename_thread(thread_id thread, const char *newName);
350extern status_t		set_thread_priority(thread_id thread, int32 newPriority);
351extern void			exit_thread(status_t status);
352extern status_t		wait_for_thread(thread_id thread, status_t *returnValue);
353extern status_t		wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout,
354						status_t *_returnCode);
355extern status_t		on_exit_thread(void (*callback)(void *), void *data);
356
357extern thread_id 	find_thread(const char *name);
358
359extern status_t		send_data(thread_id thread, int32 code, const void *buffer,
360						size_t bufferSize);
361extern int32		receive_data(thread_id *sender, void *buffer,
362						size_t bufferSize);
363extern bool			has_data(thread_id thread);
364
365extern status_t		snooze(bigtime_t amount);
366extern status_t		snooze_etc(bigtime_t amount, int timeBase, uint32 flags);
367extern status_t		snooze_until(bigtime_t time, int timeBase);
368
369/* system private, use macros instead */
370extern status_t		_get_thread_info(thread_id id, thread_info *info, size_t size);
371extern status_t		_get_next_thread_info(team_id team, int32 *cookie,
372						thread_info *info, size_t size);
373
374#define get_thread_info(id, info) \
375	_get_thread_info((id), (info), sizeof(*(info)))
376
377#define get_next_thread_info(team, cookie, info) \
378	_get_next_thread_info((team), (cookie), (info), sizeof(*(info)))
379
380/* bridge to the pthread API */
381extern thread_id	get_pthread_thread_id(pthread_t thread);
382/* TODO: Would be nice to have, but we use TLS to associate a thread with its
383   pthread object. So this is not trivial to implement.
384extern status_t		convert_to_pthread(thread_id thread, pthread_t *_thread);
385*/
386
387
388/* Time */
389
390extern unsigned long real_time_clock(void);
391extern void			set_real_time_clock(unsigned long secsSinceJan1st1970);
392extern bigtime_t	real_time_clock_usecs(void);
393extern bigtime_t	system_time(void);
394						/* time since booting in microseconds */
395extern nanotime_t	system_time_nsecs(void);
396						/* time since booting in nanoseconds */
397
398/* Alarm */
399
400enum {
401	B_ONE_SHOT_ABSOLUTE_ALARM	= 1,
402	B_ONE_SHOT_RELATIVE_ALARM,
403	B_PERIODIC_ALARM			/* "when" specifies the period */
404};
405
406extern bigtime_t	set_alarm(bigtime_t when, uint32 flags);
407
408
409/* Debugger */
410
411extern void			debugger(const char *message);
412
413/*
414   calling this function with a non-zero value will cause your thread
415   to receive signals for any exceptional conditions that occur (i.e.
416   you'll get SIGSEGV for data access exceptions, SIGFPE for floating
417   point errors, SIGILL for illegal instructions, etc).
418
419   to re-enable the default debugger pass a zero.
420*/
421extern int			disable_debugger(int state);
422
423/* TODO: Remove. Temporary debug helper. */
424extern void			debug_printf(const char *format, ...)
425						__attribute__ ((format (__printf__, 1, 2)));
426extern void			debug_vprintf(const char *format, va_list args);
427extern void			ktrace_printf(const char *format, ...)
428						__attribute__ ((format (__printf__, 1, 2)));
429extern void			ktrace_vprintf(const char *format, va_list args);
430
431
432/* System information */
433
434typedef struct {
435	bigtime_t	active_time;	/* usec of doing useful work since boot */
436	bool		enabled;
437	uint64		current_frequency;
438} cpu_info;
439
440typedef struct {
441	bigtime_t		boot_time;			/* time of boot (usecs since 1/1/1970) */
442
443	uint32			cpu_count;			/* number of cpus */
444
445	uint64			max_pages;			/* total # of accessible pages */
446	uint64			used_pages;			/* # of accessible pages in use */
447	uint64			cached_pages;
448	uint64			block_cache_pages;
449	uint64			ignored_pages;		/* # of ignored/inaccessible pages */
450
451	uint64			needed_memory;
452	uint64			free_memory;
453
454	uint64			max_swap_pages;
455	uint64			free_swap_pages;
456
457	uint32			page_faults;		/* # of page faults */
458
459	uint32			max_sems;
460	uint32			used_sems;
461
462	uint32			max_ports;
463	uint32			used_ports;
464
465	uint32			max_threads;
466	uint32			used_threads;
467
468	uint32			max_teams;
469	uint32			used_teams;
470
471	char			kernel_name[B_FILE_NAME_LENGTH];
472	char			kernel_build_date[B_OS_NAME_LENGTH];
473	char			kernel_build_time[B_OS_NAME_LENGTH];
474
475	int64			kernel_version;
476	uint32			abi;				/* the system API */
477} system_info;
478
479enum topology_level_type {
480	B_TOPOLOGY_UNKNOWN,
481	B_TOPOLOGY_ROOT,
482	B_TOPOLOGY_SMT,
483	B_TOPOLOGY_CORE,
484	B_TOPOLOGY_PACKAGE
485};
486
487enum cpu_platform {
488	B_CPU_UNKNOWN,
489	B_CPU_x86,
490	B_CPU_x86_64,
491	B_CPU_PPC,
492	B_CPU_PPC_64,
493	B_CPU_M68K,
494	B_CPU_ARM,
495	B_CPU_ARM_64,
496	B_CPU_ALPHA,
497	B_CPU_MIPS,
498	B_CPU_SH,
499	B_CPU_SPARC,
500	B_CPU_RISC_V
501};
502
503enum cpu_vendor {
504	B_CPU_VENDOR_UNKNOWN,
505	B_CPU_VENDOR_AMD,
506	B_CPU_VENDOR_CYRIX,
507	B_CPU_VENDOR_IDT,
508	B_CPU_VENDOR_INTEL,
509	B_CPU_VENDOR_NATIONAL_SEMICONDUCTOR,
510	B_CPU_VENDOR_RISE,
511	B_CPU_VENDOR_TRANSMETA,
512	B_CPU_VENDOR_VIA,
513	B_CPU_VENDOR_IBM,
514	B_CPU_VENDOR_MOTOROLA,
515	B_CPU_VENDOR_NEC,
516	B_CPU_VENDOR_HYGON,
517	B_CPU_VENDOR_SUN,
518	B_CPU_VENDOR_FUJITSU
519};
520
521typedef struct {
522	enum cpu_platform		platform;
523} cpu_topology_root_info;
524
525typedef struct {
526	enum cpu_vendor			vendor;
527	uint32					cache_line_size;
528} cpu_topology_package_info;
529
530typedef struct {
531	uint32					model;
532	uint64					default_frequency;
533} cpu_topology_core_info;
534
535typedef struct {
536	uint32							id;
537	enum topology_level_type		type;
538	uint32							level;
539
540	union {
541		cpu_topology_root_info		root;
542		cpu_topology_package_info	package;
543		cpu_topology_core_info		core;
544	} data;
545} cpu_topology_node_info;
546
547
548extern status_t		get_system_info(system_info* info);
549extern status_t		_get_cpu_info_etc(uint32 firstCPU, uint32 cpuCount,
550						cpu_info* info, size_t size);
551#define get_cpu_info(firstCPU, cpuCount, info) \
552	_get_cpu_info_etc((firstCPU), (cpuCount), (info), sizeof(*(info)))
553
554extern status_t		get_cpu_topology_info(cpu_topology_node_info* topologyInfos,
555						uint32* topologyInfoCount);
556
557#if defined(__i386__) || defined(__x86_64__)
558typedef union {
559	struct {
560		uint32	max_eax;
561		char	vendor_id[12];
562	} eax_0;
563
564	struct {
565		uint32	stepping		: 4;
566		uint32	model			: 4;
567		uint32	family			: 4;
568		uint32	type			: 2;
569		uint32	reserved_0		: 2;
570		uint32	extended_model	: 4;
571		uint32	extended_family	: 8;
572		uint32	reserved_1		: 4;
573
574		uint32	brand_index		: 8;
575		uint32	clflush			: 8;
576		uint32	logical_cpus	: 8;
577		uint32	apic_id			: 8;
578
579		uint32	features;
580		uint32	extended_features;
581	} eax_1;
582
583	struct {
584		uint8	call_num;
585		uint8	cache_descriptors[15];
586	} eax_2;
587
588	struct {
589		uint32	reserved[2];
590		uint32	serial_number_high;
591		uint32	serial_number_low;
592	} eax_3;
593
594	char		as_chars[16];
595
596	struct {
597		uint32	eax;
598		uint32	ebx;
599		uint32	edx;
600		uint32	ecx;
601	} regs;
602} cpuid_info;
603
604extern status_t		get_cpuid(cpuid_info *info, uint32 eaxRegister,
605						uint32 cpuNum);
606#endif
607
608
609extern int32		is_computer_on(void);
610extern double		is_computer_on_fire(void);
611
612
613/* signal related functions */
614int		send_signal(thread_id threadID, unsigned int signal);
615void	set_signal_stack(void* base, size_t size);
616
617
618/* WARNING: Experimental API! */
619
620enum {
621	B_OBJECT_TYPE_FD		= 0,
622	B_OBJECT_TYPE_SEMAPHORE	= 1,
623	B_OBJECT_TYPE_PORT		= 2,
624	B_OBJECT_TYPE_THREAD	= 3
625};
626
627enum {
628	B_EVENT_READ				= 0x0001,	/* FD/port readable */
629	B_EVENT_WRITE				= 0x0002,	/* FD/port writable */
630	B_EVENT_ERROR				= 0x0004,	/* FD error */
631	B_EVENT_PRIORITY_READ		= 0x0008,	/* FD priority readable */
632	B_EVENT_PRIORITY_WRITE		= 0x0010,	/* FD priority writable */
633	B_EVENT_HIGH_PRIORITY_READ	= 0x0020,	/* FD high priority readable */
634	B_EVENT_HIGH_PRIORITY_WRITE	= 0x0040,	/* FD high priority writable */
635	B_EVENT_DISCONNECTED		= 0x0080,	/* FD disconnected */
636
637	B_EVENT_ACQUIRE_SEMAPHORE	= 0x0001,	/* semaphore can be acquired */
638
639	B_EVENT_INVALID				= 0x1000,	/* FD/port/sem/thread ID not or
640											   no longer valid (e.g. has been
641											   close/deleted) */
642};
643
644typedef struct object_wait_info {
645	int32		object;						/* ID of the object */
646	uint16		type;						/* type of the object */
647	uint16		events;						/* events mask */
648} object_wait_info;
649
650/* wait_for_objects[_etc]() waits until at least one of the specified events or,
651   if given, the timeout occurred. When entering the function the
652   object_wait_info::events field specifies the events for each object the
653   caller is interested in. When the function returns the fields reflect the
654   events that actually occurred. The events B_EVENT_INVALID, B_EVENT_ERROR,
655   and B_EVENT_DISCONNECTED don't need to be specified. They will always be
656   reported, when they occur. */
657
658extern ssize_t		wait_for_objects(object_wait_info* infos, int numInfos);
659extern ssize_t		wait_for_objects_etc(object_wait_info* infos, int numInfos,
660						uint32 flags, bigtime_t timeout);
661
662
663#ifdef __cplusplus
664}
665#endif
666
667#endif /* _OS_H */
668