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