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