libk  Check-in [269baab90a]

Overview
Comment:check in missing files
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 269baab90a0d97cbfb1984d1590ea42b227ee4fffc7fac55f3f507dda4472053
User & Date: lexi on 2019-08-22 08:45:23
Other Links: manifest | tags
Context
2019-08-22
08:52
add tests for linear allocators, fix dumb bug in kmheapf() that caused it to return an error on success check-in: f37ee769c9 user: lexi tags: trunk
08:45
check in missing files check-in: 269baab90a user: lexi tags: trunk
08:44
add kmlini() and kmlina() functions; restructure allocation functions to work more reasonably (returning a tuple struct instead of making a user pass in a void**); update docs accordingly check-in: acb4a9944e user: lexi tags: trunk
Changes

Added mod/kcli/kcli.md version [09b7990027].





























































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# kcli
**kcli** is a module that implements common routines used by command-line utilities, such as option parsing, usage display, and more.

## functions

### kcli_usage(kcli_set, kiochan)
kcli_usage() takes a `kcli_set` and prints a succinct usage summary to a [kiochan](../kio/kio.md).

## types

### struct kcli_set
`kcli_set` is a struct containing information about your program, such as its name, a synopsis of its function, a pointer to `argv`, and a list of `kcli_opt`s.

 * `const char* name` - program name (if null, will be determined from argv instead)
 * `size_t argc` - the number of arguments in the `argv` array.
 * `const char** argv` - the `argv` pointer passed to the `entry` function, representing the command-line arguments passed to the program.
 * `const char* desc` - program description
 * `const kcli_param* params` - a list of options expected by the program.
 * `size_t paramc` - the number of params in the list to process.
 * `const kcli_opt* opts` - a list of options expected by the program.
 * `size_t optc` - the number of options in the list to process.

a kcli_set might be used like so:

    #include <k/core.h>
    #include <k/io.h>
    #include <k/cli.h>
    stat entry(kenv e) {
    	kcli_flag aardvark;
    	kcli_flag zebra;
    	char* user;
    	char* password;
		long age;
		kcli_param params[] = {
    		{ "user", kcli_param_string, kcli_class_required,
    		  &user, "the user to log in as" }
			  // or Kcli_param(user,string,required,"the user to log in as"),

			{ "age", kcli_param_dec, kcli_class_optional,
    		  &age, "the age of the user" }
			  // or Kcli_param(age,dec,optional,"the age of the user"),
		};
    	kcli_opt options[] = {
    		{ 'a', "aardvark", kcli_opt_flag, &aardvark,
    		  "a nocturnal burrowing mammal" },
			  // or Kcli_opt(aardvark, 'a', flag, "a nocturnal burrowing mammal")
    		{ 'z', "zebra", kcli_opt_flag, &zebra,
    		  "a striped equine" },
    		{ 'p', "password", kcli_opt_string, &password,
    		  "the password to log in with" }
    	};
    	kcli_set argset = {
    		"demo", e.argc, e.argv,
    		"a demonstration of the kcli_set type",
			params, Kmsz(params),
			options, Kmsz(options)
    	},
		size_t args_parsed = kcli_parse(&argset);
		if (args_parsed == 0) { kcli_usage(&me, e.err); return 1; }

		return 0;
	}

### struct kcli_opt
a `kcli_opt` is a representation of a command-line flag and its function. each option must have a unique `id` and/or a unique `name`.

 * `char id` - the short single-character form of the flag (or NUL for no short form)
 * `const char* name` - the long string form of the flag (or NULL for no long form)
 * `kcli_opt_kind kind` - enum that describes how the flag will function
 * `void* val` - a pointer to an appropriate type to store the return value in.
 * `const char* desc` - a description of the flag's purpose and function (or NULL for no description)

#### enum kcli_opt_kind

 * `kcli_opt_none` - flag is disabled and will not be shown in usage
 * `kcli_opt_string` - flag tells kcli to add a string to the list of expected parameters; appropriate string will be returned
 * `kcli_opt_oct` - flag tells kcli to add an octal number to the list of expected parameters
 * `kcli_opt_dec` - flag tells kcli to add a decimal number to the list of expected parameters
 * `kcli_opt_hex` - flag tells kcli to add a hexdecimal number to the list of expected parameters
 * `kcli_opt_flag` - flag is an option: will return `kcli_flag_on` if entered at least once, `kcli_flag_off` otherwise.
 * `kcli_opt_toggle` - flag toggles value on and off: will return `kcli_flag_on` if entered an odd number of times, `kcli_flag_off` otherwise.
 * `kcli_opt_accumulate` - flag increments a value every time it is entered; often used to implement `-v (--verbose)`-style options (e.g. `-vvvv` would return a value of `4`).
 * `kcli_opt_enum` - flag is one of a series of enumerated values, which will be matched against a table to yield the associated integer.

### struct kcli_param
`kcli_param` describes a parameter that may be passed to the program whether or not any flags are passed.

 * `const char* name` - a short name for the parameter
 * `kcli_param_kind kind` - the kind of parameter passed
 * `kcli_class class` - whether or not the parameter is optional
 * `void* val` - a pointer to an appropriate type of variable to fill
 * `const char* desc` - a description of the parameter's function

#### enum kcli_param_kind
 * `kcli_param_none` - parameter is disabled and will not be expected or accepted
 * `kcli_param_string` - parameter will not be parsed; a raw string will be returned
 * `kcli_param_oct` - parameter will be parsed as an octal number
 * `kcli_param_dec` - parameter will be parsed as a decimal number
 * `kcli_param_hex` - parameter will be parsed as a hexadecimal number

### enum kcli_class
 * `kcli_class_forbidden` - parameter may not be passed
 * `kcli_class_optional` - parameter may or may not be passed
 * `kcli_class_required` - parameter must be passed

### enum kcli_flag
results that an option of kind `kcli_opt_flag` can return.

 * `kcli_flag_off = 0` - flag is off
 * `kcli_flag_on = 1` - flag is on
 
## macros

### Kcli_param(field, kind, class, description)
a convenience macro for filling out parameter lists.

`Kcli_param(field,a,b,"description")` is transformed into:

    { "field", kcli_param_a, kcli_class_b, &field, "description" }

### Kcli_opt(field, kind, class, description)
a convenience macro for filling out option lists.

`Kcli_opt(name,'n',string,"description")` is transformed into:

    { 'n', "name", kcli_opt_string, &name, "description" }

Added mod/kcore/okay.fn.c version [4f27230207].















>
>
>
>
>
>
>
1
2
3
4
5
6
7
#include <k/core.h>
#include <k/type.h>
#include <k/internal.egroup.h>

bool kokay(kcond val) {
	return (val % kglobal_module_offset) == 0;
}

Added mod/kcore/syscall.fn.x86.lin.32.s version [78de383598].











































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
; kcore/syscall.fn.x86.lin.32.s
; ~ lexi hale <lexi@hale.su>
;
; this function performs a syscall and stores its
; results in the variables provided. this makes it
; possible to bypass the hideous errno mechanism
; altogether and access the error value of a
; syscall directly. invoke as:
;
; 	void k_platform_syscall_raw(s32* result, u32* errno,
;		syscall, u8 valency, s32[] args)

bits 32
%include "../arch/posix/x86.lin.32.s"
%include "../arch/x86.cdecl.32.s"
; vim: ft=nasm


%define result_ptr edi
%define errno_ptr ebx
%define valency ecx
%define args esi
%define opcode eax

%macro handle_arg 1
	push dword [args]
	sub args, 4
	dec valency 
	jz .perform_call
%endmacro

global k_platform_syscall_raw:function
k_platform_syscall_raw:
	; locals: rbx = s32* result
	;         r12 = u32* errno
	; arg 0 = s32* result
	; arg 1 = errno ptr
	; arg 2 = syscall num
	; arg 3 = valency
	; arg 4 = args ptr

	; store the locals in registers that
	; are guaranteed not to be clobbered,
	; saving us some cycles pushing to
	; and popping back from the stack
	pop result_ptr 
	pop errno_ptr
	pop edx ; opcode

	; set up registers for the loop
	pop valency
	pop args ; ptr to args array
	mov eax, 4
	mul valency
	add args, eax ; adjust args pointer to point
	              ; at end of array, so it can be
				  ; trivially pushed in backwards

	; this needs to go before the loop
	; or it'll get clobbered
	mov opcode, edx ; syscall number

	; automatically generate the code
	; needed to move the arguments into
	; their correct registers. see above
	%assign i 0
	%rep 6
		handle_arg i
		%assign i i+1
	%endrep

	; valency >= 7. this is not valid, so
	; we set our return value to 0 and the
	; error number to its maximum value in
	; order to indicate that the syscall
	; was invalid
	mov dword [result_ptr], -1
	mov dword [errno_ptr], -1
	ret

	; we have a valency match - perform the
	; requested syscall already stored in eax
	.perform_call: sys.call

	; check if an error has occurred, and
	; jump to the error handling routine
	; if necessary
	test sys.reg.ret, sys.reg.ret
	js .error
	
	; move our return values into place and
	; return to the caller (which should
	; always be k_platform_syscall, btw)
	mov       [result_ptr], sys.reg.ret
	mov dword [errno_ptr], 0
	ret

	.error: neg sys.reg.ret
	        mov dword [result_ptr], -1
			mov       [errno_ptr], sys.reg.ret
			ret

Added mod/kmem/lina.fn.c version [0011a847e1].































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/* lina.fn.c - kmlina() - linear allocate
 * ~ lexi hale <lexi@hale.su>
 * kmlina() allocates the requested amount of space on
 * the heap and returns a pointer to it. it allocates
 * this memory simply by growing the heap the proper
 * length. */

#include <k/mem.h>
#include <k/def.h>

#ifdef KFenv_posix
#	include <posix/posix.h>
#endif

kmres kmlina(sz size) {
	k_platform_syscall_arg
		   top = (sz)kmlini(),
		newbrk = top + size;

	struct k_platform_syscall_answer a = k_platform_syscall
		(k_platform_syscall_brk, 1, &newbrk);

	kmres reply;

	if (a.error != 0) reply.cond = kmcond_no_room,
	                  reply.raw = 0;
		else reply.cond = kmcond_ok,
			 reply.raw = (void*)a.ret;

	return reply;
}

Added mod/kmem/lini.fn.c version [99be01eb40].



























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* lini.fn.c - kmlini() - initiate a linear segment
 * ~ lexi hale <lexi@hale.su>
 * this function is the initiator function for the
 * linear memory store. it simply returns the current
 * heap position by invoking the brk syscall with the
 * value `0`. (note that the brk syscall and the libc
 * wrapper have different behavior.) */

#include <k/mem.h>
#include <k/def.h>

#ifdef KFenv_posix
#	include <posix/posix.h>
#endif

/* returns void* instead of kmres because kmlini has
 * no failure state */
void* kmlini(void) {
	k_platform_syscall_arg zero = 0;
	/* brk adjusts the heap break then returns the new
	 * break. by passing zero, we can get retrieve the
	 * current heap break. */
	struct k_platform_syscall_answer a = k_platform_syscall
		(k_platform_syscall_brk, 1, &zero);

	/* no point in checking for errors, since none can
	 * actually occur; just return the kernel's answer. */
	return (void*)a.ret;
}