Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 7536 → Rev 7537

/programs/develop/ktcc/trunk/libc/include/kos32sys1beta.h
0,0 → 1,994
#ifndef __KOS_32_SYS_H__
#define __KOS_32_SYS_H__
 
// file header taken from newlib
// added many sys functions, compatible with tcc
// with gcc USE gcc -mno-ms-bitfields!!!
 
 
//#include <newlib.h>
//#include <stdint.h>
#include <stddef.h>
#include <stdarg.h>
typedef unsigned int uint32_t;
typedef int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned long long uint64_t;
 
#ifdef __cplusplus
extern "C" {
#endif
 
//#ifdef CONFIG_DEBUF
// #define DBG(format,...) printf(format,##__VA_ARGS__)
//#else
// #define DBG(format,...)
//#endif
 
#define TYPE_3_BORDER_WIDTH 5
#define WIN_STATE_MINIMIZED 0x02
#define WIN_STATE_ROLLED 0x04
#define POS_SCREEN 0
#define POS_WINDOW 1
 
#define IPC_NOBUFFER 1
#define IPC_LOCKED 2
#define IPC_OVERFLOW 3
#define IPC_NOPID 4
 
#define SHM_OPEN 0x00
#define SHM_OPEN_ALWAYS 0x04
#define SHM_CREATE 0x08
#define SHM_READ 0x00
#define SHM_WRITE 0x01
 
 
typedef unsigned int color_t;
 
 
typedef union __attribute__((packed)) pos_t
{
uint32_t val;
struct
{
short x;
short y;
};
} pos_t;
 
 
typedef union __attribute__((packed)) oskey_t
{
uint32_t val;
struct
{
uint8_t state;
uint8_t code;
uint16_t ctrl_key;
};
} oskey_t;
 
typedef struct
{
unsigned handle;
unsigned io_code;
void *input;
int inp_size;
void *output;
int out_size;
}ioctl_t;
 
typedef union
{
struct
{
void *data;
size_t size;
} x;
unsigned long long raw;
}ufile_t;
 
struct kolibri_system_colors {
color_t frame_area;
color_t grab_bar;
color_t grab_bar_button;
color_t grab_button_text;
color_t grab_text;
color_t work_area;
color_t work_button;
color_t work_button_text;
color_t work_text;
color_t work_graph;
};
 
 
struct blit_call
{
int dstx;
int dsty;
int w;
int h;
 
int srcx;
int srcy;
int srcw;
int srch;
 
void *bitmap;
int stride;
};
 
struct ipc_message
{
uint32_t pid; // PID of sending thread
uint32_t datalen; // data bytes
char data[0]; // data begin
};
 
struct ipc_buffer
{
uint32_t lock; // nonzero is locked
uint32_t used; // used bytes in buffer
struct ipc_message data[0]; // data begin
};
 
 
typedef struct __attribute__((packed)) file_op_t
{
uint32_t fn;
uint32_t flags;
char* args;
uint32_t res1, res2;
char zero;
char* app_name
#ifdef __TINYC__
__attribute__((packed))
#endif
;
} file_op_t;
 
 
static inline void begin_draw(void)
{
__asm__ __volatile__(
"int $0x40" ::"a"(12),"b"(1));
};
 
static inline
void end_draw(void)
{
__asm__ __volatile__(
"int $0x40" ::"a"(12),"b"(2));
};
 
static inline
void sys_create_window(int x, int y, int w, int h, const char *name,
color_t workcolor, uint32_t style)
{
__asm__ __volatile__(
"int $0x40"
::"a"(0),
"b"((x << 16) | ((w-1) & 0xFFFF)),
"c"((y << 16) | ((h-1) & 0xFFFF)),
"d"((style << 24) | (workcolor & 0xFFFFFF)),
"D"(name),
"S"(0) : "memory");
};
 
static inline
void define_button(uint32_t x_w, uint32_t y_h, uint32_t id, uint32_t color)
{
__asm__ __volatile__(
"int $0x40"
::"a"(8),
"b"(x_w),
"c"(y_h),
"d"(id),
"S"(color));
};
 
static inline
void draw_line(int xs, int ys, int xe, int ye, color_t color)
{
__asm__ __volatile__(
"int $0x40"
::"a"(38), "d"(color),
"b"((xs << 16) | xe),
"c"((ys << 16) | ye));
}
 
static inline
void draw_bar(int x, int y, int w, int h, color_t color)
{
__asm__ __volatile__(
"int $0x40"
::"a"(13), "d"(color),
"b"((x << 16) | w),
"c"((y << 16) | h));
}
 
static inline
void draw_bitmap(void *bitmap, int x, int y, int w, int h)
{
__asm__ __volatile__(
"int $0x40"
::"a"(7), "b"(bitmap),
"c"((w << 16) | h),
"d"((x << 16) | y));
}
 
static inline
void draw_text_sys(const char *text, int x, int y, int len, color_t color)
{
__asm__ __volatile__(
"int $0x40"
::"a"(4),"d"(text),
"b"((x << 16) | y),
"S"(len),"c"(color)
:"memory");
}
 
static inline
uint32_t get_skin_height(void)
{
uint32_t height;
 
__asm__ __volatile__(
"int $0x40 \n\t"
:"=a"(height)
:"a"(48),"b"(4));
return height;
};
 
static inline
pos_t get_mouse_pos(int origin)
{
pos_t val;
 
__asm__ __volatile__(
"int $0x40 \n\t"
"rol $16, %%eax"
:"=a"(val)
:"a"(37),"b"(origin));
return val;
}
 
static inline
uint32_t get_mouse_buttons(void)
{
uint32_t val;
 
__asm__ __volatile__(
"int $0x40"
:"=a"(val)
:"a"(37),"b"(2));
return val;
};
 
static inline
uint32_t get_mouse_wheels(void)
{
uint32_t val;
 
__asm__ __volatile__(
"int $0x40 \n\t"
:"=a"(val)
:"a"(37),"b"(7));
return val;
};
 
static inline uint32_t load_cursor(void *path, uint32_t flags)
{
uint32_t val;
__asm__ __volatile__(
"int $0x40"
:"=a"(val)
:"a"(37), "b"(4), "c"(path), "d"(flags));
return val;
}
 
static inline uint32_t set_cursor(uint32_t cursor)
{
uint32_t old;
__asm__ __volatile__(
"int $0x40"
:"=a"(old)
:"a"(37), "b"(5), "c"(cursor));
return old;
};
 
static inline int destroy_cursor(uint32_t cursor)
{
int ret;
__asm__ __volatile__(
"int $0x40"
:"=a"(ret)
:"a"(37), "b"(6), "c"(cursor)
:"memory");
return ret;
};
 
 
static inline
uint32_t wait_for_event(uint32_t time)
{
uint32_t val;
__asm__ __volatile__(
"int $0x40"
:"=a"(val)
:"a"(23), "b"(time));
return val;
};
 
static inline uint32_t check_os_event()
{
uint32_t val;
__asm__ __volatile__(
"int $0x40"
:"=a"(val)
:"a"(11));
return val;
};
 
static inline uint32_t get_os_event()
{
uint32_t val;
__asm__ __volatile__(
"int $0x40"
:"=a"(val)
:"a"(10));
return val;
};
 
static inline
uint32_t get_tick_count(void)
{
uint32_t val;
__asm__ __volatile__(
"int $0x40"
:"=a"(val)
:"a"(26),"b"(9));
return val;
};
 
static inline
uint64_t get_ns_count(void)
{
uint64_t val;
__asm__ __volatile__(
"int $0x40"
:"=A"(val)
:"a"(26), "b"(10));
return val;
};
 
static inline
oskey_t get_key(void)
{
oskey_t val;
__asm__ __volatile__(
"int $0x40"
:"=a"(val)
:"a"(2));
return val;
}
 
static inline
uint32_t get_os_button()
{
uint32_t val;
__asm__ __volatile__(
"int $0x40"
:"=a"(val)
:"a"(17));
return val>>8;
};
 
static inline uint32_t get_service(char *name)
{
uint32_t retval = 0;
__asm__ __volatile__(
"int $0x40"
:"=a"(retval)
:"a"(68),"b"(16),"c"(name)
:"memory");
 
return retval;
};
 
static inline int call_service(ioctl_t *io)
{
int retval;
 
__asm__ __volatile__(
"int $0x40"
:"=a"(retval)
:"a"(68),"b"(17),"c"(io)
:"memory","cc");
 
return retval;
};
 
 
static inline void yield(void)
{
__asm__ __volatile__(
"int $0x40"
::"a"(68), "b"(1));
};
 
static inline void delay(uint32_t time)
{
__asm__ __volatile__(
"int $0x40"
::"a"(5), "b"(time)
:"memory");
};
 
static inline
void *user_alloc(size_t size)
{
void *val;
__asm__ __volatile__(
"int $0x40"
:"=a"(val)
:"a"(68),"b"(12),"c"(size));
return val;
}
 
static inline
int user_free(void *mem)
{
int val;
__asm__ __volatile__(
"int $0x40"
:"=a"(val)
:"a"(68),"b"(13),"c"(mem));
return val;
}
 
static inline
void* user_realloc(void *mem, size_t size)
{
void *val;
__asm__ __volatile__(
"int $0x40"
:"=a"(val)
:"a"(68),"b"(20),"c"(size),"d"(mem)
:"memory");
 
return val;
};
 
static inline
int *user_unmap(void *base, size_t offset, size_t size)
{
int *val;
__asm__ __volatile__(
"int $0x40"
:"=a"(val)
:"a"(68),"b"(26),"c"(base),"d"(offset),"S"(size));
return val;
};
 
static inline ufile_t load_file(const char *path)
{
ufile_t uf;
 
__asm__ __volatile__ (
"int $0x40"
:"=A"(uf.raw)
:"a" (68), "b"(27),"c"(path));
 
return uf;
};
 
static inline int GetScreenSize()
{
int retval;
 
__asm__ __volatile__(
"int $0x40"
:"=a"(retval)
:"a"(61), "b"(1));
return retval;
}
 
 
static inline void get_proc_info(char *info)
{
__asm__ __volatile__(
"int $0x40"
:
:"a"(9), "b"(info), "c"(-1)
:"memory");
};
 
static inline void Blit(void *bitmap, int dst_x, int dst_y,
int src_x, int src_y, int w, int h,
int src_w, int src_h, int stride)
{
volatile struct blit_call bc;
 
bc.dstx = dst_x;
bc.dsty = dst_y;
bc.w = w;
bc.h = h;
bc.srcx = src_x;
bc.srcy = src_y;
bc.srcw = src_w;
bc.srch = src_h;
bc.stride = stride;
bc.bitmap = bitmap;
 
__asm__ __volatile__(
"int $0x40"
::"a"(73),"b"(0),"c"(&bc.dstx));
};
 
 
// newlib exclusive
#ifndef __TINYC__
int create_thread(int (*proc)(void *param), void *param, int stack_size);
 
void* load_library(const char *name);
 
void* get_proc_address(void *handle, const char *proc_name);
 
void enumerate_libraries(int (*callback)(void *handle, const char* name,
uint32_t base, uint32_t size, void *user_data),
void *user_data);
#endif
 
///////////////////////////////////////////////////////////////////////////////
/// May be next section need to be added in newlibc
// Siemargl addenium
 
#define X_Y(x,y) (((x)<<16)|(y))
 
enum KOLIBRI_GUI_EVENTS {
KOLIBRI_EVENT_NONE = 0, /* Event queue is empty */
KOLIBRI_EVENT_REDRAW = 1, /* Window and window elements should be redrawn */
KOLIBRI_EVENT_KEY = 2, /* A key on the keyboard was pressed */
KOLIBRI_EVENT_BUTTON = 3, /* A button was clicked with the mouse */
KOLIBRI_EVENT_DESKTOP = 5, /* Desktop redraw finished */
KOLIBRI_EVENT_MOUSE = 6, /* Mouse activity (movement, button press) was detected */
KOLIBRI_EVENT_IPC = 7, /* Interprocess communication notify */
KOLIBRI_EVENT_NETWORK = 8, /* Network event */
KOLIBRI_EVENT_DEBUG = 9, /* Debug subsystem event */
KOLIBRI_EVENT_IRQBEGIN = 16 /* 16..31 IRQ0..IRQ15 interrupt =IRQBEGIN+IRQn */
};
 
enum control_keys {
KM_SHIFT = 0x00010000,
KM_CTRL = 0x00020000,
KM_ALT = 0x00040000,
KM_NUMLOCK = 0x00080000
};
 
 
struct __attribute__ ((__packed__)) fs_dirinfo {
uint32_t subfn; // 1 read dir
uint32_t start;
uint32_t flags;
uint32_t size;
uint32_t retval;
union {
struct __attribute__ ((__packed__)) {
uint8_t zero; // 0
char* ppath;
};
char path[5]; // up to 4096
} ;
};
 
static inline
uint32_t sf_file(int subfn, struct fs_dirinfo* dinfo)
/// SysFn70 call with subfunction
/// retval 0 if ok
{
uint32_t retval;
dinfo->subfn = subfn;
 
__asm__ __volatile__(
"int $0x40 "
:"=a"(retval)
:"a"(70),"b"(dinfo)
:);
 
return retval;
};
 
 
struct fs_dirheader {
uint32_t version; // 1
uint32_t curn_blocks; // number of read dir items (BDFE)
uint32_t totl_blocks; // directory full size
char other[20]; // reserved 0
};
 
enum filetype
{
FS_RONLY = 1,
FS_HIDDEN = 2,
FS_SYSTEM = 4,
FS_VOLID = 8,
FS_SUBDIR = 16,
FS_FOLDER = 16,
FS_ARCHIV = 32
};
 
struct __attribute__ ((__packed__)) fs_filetime {
uint8_t sec;
uint8_t mm;
uint8_t hour;
uint8_t zero;
};
 
struct __attribute__ ((__packed__)) fs_filedate {
uint8_t day;
uint8_t month;
uint16_t year;
};
 
/// directory entry cp866
struct fsBDFE {
uint32_t filetype;
uint32_t encoding; // 0 - cp866, 1 - utf16le
struct fs_filetime tm_created;
struct fs_filedate dt_created;
struct fs_filetime tm_accessed;
struct fs_filedate dt_accessed;
struct fs_filetime tm_modified;
struct fs_filedate dt_modified;
uint64_t size;
char fname[264];
}; // must be sized 304
 
/// directory entry UTF16LE
struct fsBDFE_16 {
uint32_t filetype;
uint32_t encoding; // 0 - cp866, 1 - utf16le
struct fs_filetime tm_created;
struct fs_filedate dt_created;
struct fs_filetime tm_accessed;
struct fs_filedate dt_accessed;
struct fs_filetime tm_modified;
struct fs_filedate dt_modified;
uint64_t size;
wchar_t fname[260];
}; // must be sized 560
 
 
 
// copied from /programs/system/shell/system/kolibri.c
// fn's returned -1 as syserror, 1 as error, 0 as OK
static inline
int kol_clip_num()
{
register uint32_t val;
asm volatile ("int $0x40":"=a"(val):"a"(54), "b"(0));
return val;
}
 
static inline
char* kol_clip_get(int n)
// returned buffer must be freed by user_free()
{
register char* val;
asm volatile ("int $0x40":"=a"(val):"a"(54), "b"(1), "c"(n));
return val;
}
 
static inline
int kol_clip_set(int n, char buffer[])
{
register uint32_t val;
asm volatile ("int $0x40":"=a"(val):"a"(54), "b"(2), "c"(n), "d"(buffer));
return val;
}
 
static inline
int kol_clip_pop()
{
register uint32_t val;
asm volatile ("int $0x40":"=a"(val):"a"(54), "b"(3));
return val;
}
 
static inline
int kol_clip_unlock()
{
register uint32_t val;
asm volatile ("int $0x40":"=a"(val):"a"(54), "b"(4));
return val;
}
 
static inline void get_system_colors(struct kolibri_system_colors *color_table)
{
__asm__ volatile ("int $0x40"
:
:"a"(48),"b"(3),"c"(color_table),"d"(40)
);
 
/* color_table should point to the system color table */
}
 
static inline void debug_board_write_byte(const char ch){
__asm__ __volatile__(
"int $0x40"
:
:"a"(63), "b"(1), "c"(ch));
}
 
 
static inline void draw_number_sys(int32_t number, int x, int y, int len, color_t color){
register uint32_t fmt;
fmt = len << 16 | 0x80000000; // no leading zeros + width
// fmt = len << 16 | 0x00000000; // leading zeros + width
__asm__ __volatile__(
"int $0x40"
:
:"a"(47), "b"(fmt), "c"(number), "d"((x << 16) | y), "S"(color));
}
 
static inline
uint32_t get_mouse_eventstate(void)
{
uint32_t val;
 
__asm__ __volatile__(
"int $0x40"
:"=a"(val)
:"a"(37),"b"(3));
return val;
};
 
static inline
uint32_t set_event_mask(uint32_t mask)
{
register uint32_t val;
asm volatile ("int $0x40":"=a"(val):"a"(40), "b"(mask));
return val;
}
 
typedef void (*thread_proc)(void*);
 
static inline
int start_thread(thread_proc proc, char* stack_top)
{
register int val;
asm volatile ("int $0x40":"=a"(val):"a"(51), "b"(1), "c"(proc), "d"(stack_top));
return val;
}
 
static inline
void kos_exit()
{
asm volatile ("int $0x40"::"a"(-1));
}
 
static inline void focus_window(int slot){
asm volatile ("int $0x40"::"a"(18), "b"(3), "c"(slot));
}
 
static inline int get_thread_slot(int tid){
register int val;
asm volatile ("int $0x40":"=a"(val):"a"(18), "b"(21), "c"(tid));
return val;
}
 
static inline void set_current_folder(char* dir){
asm volatile ("int $0x40"::"a"(30), "b"(1), "c"(dir));
}
 
static inline int get_current_folder(char* buf, int bufsize){
register int val;
asm volatile ("int $0x40":"=a"(val):"a"(30), "b"(2), "c"(buf), "d"(bufsize));
return val;
}
 
static inline
void ipc_set_area(void* buf, int bufsize){
asm volatile ("int $0x40"::"a"(60), "b"(1), "c"(buf), "d"(bufsize));
}
 
static inline
int ipc_send_message(int pid_reciever, void *data, int datalen) {
register int val;
asm volatile ("int $0x40":"=a"(val):"a"(60), "b"(2), "c"(pid_reciever), "d"(data), "S"(datalen));
return val;
}
 
static inline
void* shm_open(char *shm_name, int msize, int flags, int *retsz){
register int val, cod;
asm volatile ("int $0x40":"=a"(val),"=d"(cod):"a"(68), "b"(22), "c"(shm_name), "d"(msize), "S"(flags));
 
if(retsz) *retsz = cod; // errcode if NULL or memsize when open
return (void*)val;
}
 
static inline
void shm_close(char *shm_name){
asm volatile ("int $0x40"::"a"(68), "b"(23), "c"(shm_name));
}
 
static inline
int start_app(char *app_name, char *args){
file_op_t file_op;
memset(&file_op, 0, sizeof(file_op));
file_op.fn = 7;
file_op.args = args;
file_op.app_name = app_name;
 
register int val;
asm volatile ("int $0x40":"=a"(val):"a"(70), "b"(&file_op));
 
return val;
}
 
static inline
uint32_t get_control_keys(void)
{
uint32_t ctrl;
 
__asm__ __volatile__(
"int $0x40 \n\t"
:"=a"(ctrl)
:"a"(66),"b"(3));
 
return ctrl;
};
 
static inline
int get_keyboard_layout(int opt, char* buf)
/// 128 byte buffer
/// opt: 1 - normal, 2 - shifted, 3 - alted, or 9 - return language
{
uint32_t lang;
 
__asm__ __volatile__(
"int $0x40 \n\t"
:"=a"(lang)
:"a"(26),"b"(2), "c"(opt), "d"(buf));
 
return lang;
};
 
 
static inline
int font_size(int color)
/// decode font size in pixels from color as SysFn4
/// returns (width, hight)
{
int font = color >> 24;
int font_multipl = (font & 7) + 1;
int width_sym, hight_sym;
 
if (font & 0x10) // 8x16
{
width_sym = 8 * font_multipl;
hight_sym = 16 * font_multipl;
} else // 6x9
{
width_sym = 6 * font_multipl;
hight_sym = 9 * font_multipl;
}
return hight_sym + (width_sym << 16);
}
 
/*
static inline char *getcwd(char *buf, size_t size)
{
int rc = get_current_folder(buf, size);
if (rc > size)
{
errno = ERANGE;
return 0;
}
else
return buf;
}
*/
/* not finished
void staticnum_draw(staticnum *st)
{
register uint32_t fmt;
if (st->width < 0)
fmt = (-st->width << 16); // leading zeros, decimal
else
fmt = (st->width << 16) | 0x80000000; // no leading zeros, decimal
 
__asm__ __volatile__(
"int $0x40"
::"a"(47),
"b"(fmt),
"c"(st->number),
"d"(st->start_xy),
"S"(st->color_flags),
"D"(st->bg_color)
:);
}
 
*/
//////////// end section
 
 
 
//added nonstatic inline because incomfortabre stepping in in debugger
void __attribute__ ((noinline)) debug_board_write_str(const char* str);
void __attribute__ ((noinline)) debug_board_printf(const char *format,...);
 
/* copy body to only one project file
void __attribute__ ((noinline)) debug_board_write_str(const char* str){
while(*str)
debug_board_write_byte(*str++);
}
 
void __attribute__ ((noinline)) debug_board_printf(const char *format,...)
{
va_list ap;
char log_board[300];
 
va_start (ap, format);
vsnprintf(log_board, sizeof log_board, format, ap);
va_end(ap);
debug_board_write_str(log_board);
}
 
__attribute__ ((noinline)) void trap(int n)
{
// nothing todo, just see n in debugger. use "bp trap" command
__asm__ __volatile__(
"nop"
:
:"a"(n));
}
 
*/
 
 
 
// TinyC don't support aliasing of static inline funcs
#ifndef __TINYC__
static inline void BeginDraw(void) __attribute__ ((alias ("begin_draw")));
static inline void EndDraw(void) __attribute__ ((alias ("end_draw")));
static inline void DrawWindow(int x, int y, int w, int h, const char *name,
color_t workcolor, uint32_t style)
__attribute__ ((alias ("sys_create_window")));
static inline void DefineButton(void) __attribute__ ((alias ("define_button")));
static inline void DrawLine(int xs, int ys, int xe, int ye, color_t color)
__attribute__ ((alias ("draw_line")));
static inline void DrawBar(int x, int y, int w, int h, color_t color)
__attribute__ ((alias ("draw_bar")));
static inline void DrawBitmap(void *bitmap, int x, int y, int w, int h)
__attribute__ ((alias ("draw_bitmap")));
static inline uint32_t GetSkinHeight(void) __attribute__ ((alias ("get_skin_height")));
static inline pos_t GetMousePos(int origin) __attribute__ ((alias ("get_mouse_pos")));
static inline uint32_t GetMouseButtons(void) __attribute__ ((alias ("get_mouse_buttons")));
static inline uint32_t GetMouseWheels(void) __attribute__ ((alias ("get_mouse_wheels")));
static inline uint32_t LoadCursor(void *path, uint32_t flags) __attribute__ ((alias ("load_cursor")));
static inline uint32_t SetCursor(uint32_t cursor) __attribute__ ((alias ("set_cursor")));
static inline int DestroyCursor(uint32_t cursor) __attribute__ ((alias ("destroy_cursor")));
static inline uint32_t GetOsEvent(void) __attribute__ ((alias ("get_os_event")));
static inline void *UserAlloc(size_t size) __attribute__ ((alias ("user_alloc")));
static inline int UserFree(void *mem) __attribute__ ((alias ("user_free")));
static inline void* UserRealloc(void *mem, size_t size) __attribute__ ((alias ("user_realloc")));
static inline int *UserUnmap(void *base, size_t offset, size_t size) __attribute__ ((alias ("user_unmap")));
static inline ufile_t LoadFile(const char *path) __attribute__ ((alias ("load_file")));
static inline void GetProcInfo(char *info) __attribute__ ((alias ("get_proc_info")));
#endif
 
#ifdef __cplusplus
}
#endif
 
 
#endif
 
 
 
 
 
/programs/develop/ktcc/trunk/libc/include/stdlib.h
32,6 → 32,7
extern void* wtcalloc (size_t num, size_t size);
extern int wtmalloc_freelist_check();
extern int wtmalloc_poiner_check(void *ptr);
extern void wtmalloc_freelist_print();
 
#ifdef USESYSALLOC
#define malloc(x) sysmalloc(x)
/programs/develop/ktcc/trunk/libc/memory/watermark.c
16,13 → 16,22
 
#ifndef NDEBUG
#include <stdio.h>
# ifdef __TINYC__
# include <kolibrisys.h>
# define TRACE1(s, a) { char buf[400]; sprintf(buf, s, a); debug_out_str(buf); }
# define TRACE2(s, a, b) { char buf[400]; sprintf(buf, s, a, b); debug_out_str(buf); }
# else
# define TRACE1(s, a) printf(s, a)
# define TRACE2(s, a, b) printf(s, a, b)
# endif
#else
# define TRACE1(s, a) (void)0
# define TRACE2(s, a, b) (void)0
#endif
 
 
 
 
// get address, fromwhere function was called
#define CALLEDFROM(param1) (*(int*)((char*)&param1-4)-5)
45,9 → 54,21
static char *__freebase = NULL; // begin of free area
static char *__freetop = NULL; // after last byte of free area
static struct hdrfree *__firstfree = NULL; // ptr to first node in dual-link list
static unsigned __crtfreeblocks = 0; // number of free blocks, checking corruptions
 
static struct {
uint32_t malloc_calls;
uint32_t malloc_max;
uint32_t malloc_sum;
 
uint32_t sysalloc_calls;
uint32_t sysalloc_max;
uint32_t sysalloc_sum;
uint32_t crtfreeblocks; // number of free blocks, checking corruptions
uint32_t freeblocks_sum;
} wtalloc_stat;
 
 
void *wtmalloc(size_t sz)
{
struct hdrfree *fndnode, *newnode;
54,6 → 75,11
sz = (sizeof(struct hdrused) + sz + 15) & ~15; // align 16bytes
//TRACE1("_call alloc(%d)\n", sz);
//statistics
wtalloc_stat.malloc_calls++;
if (sz > wtalloc_stat.malloc_max) wtalloc_stat.malloc_max = sz;
wtalloc_stat.malloc_sum += sz;
// try to find free block enough size
fndnode = __firstfree;
while(fndnode)
74,6 → 100,7
if (fndnode->size - sz > 15) // split smaller size, move free node
{
//TRACE2("alloc(%d) split (%x)\n", sz, fndnode);
wtalloc_stat.freeblocks_sum -= sz;
newnode = (struct hdrfree*)((char*)fndnode + sz);
newnode->mark = c_free;
newnode->size = fndnode->size - sz;
84,22 → 111,23
fndnode->next->prev = newnode;
//перед может быть не нода, а 1й указатель
if (!fndnode->prev)
if (fndnode->prev)
newnode->prev->next = newnode;
else
__firstfree = newnode;
else
newnode->prev->next = newnode;
} else // nothing to split, just exclude
{
//TRACE1("alloc(%d) remove freenode\n", sz);
 
__crtfreeblocks--;
wtalloc_stat.crtfreeblocks--;
wtalloc_stat.freeblocks_sum -= fndnode->size;
if (fndnode->next)
fndnode->next->prev = fndnode->prev;
//перед может быть не нода, а 1й указатель
if (!fndnode->prev)
if (fndnode->prev)
fndnode->prev->next = fndnode->next;
else
__firstfree = fndnode->next;
else
fndnode->prev->next = fndnode->next;
}
fndnode->mark = c_used;
112,8 → 140,15
if (__freetop - __freebase < sz) // not enough memory - call system
{
if (sz > UINT_MAX - 16) return NULL; // check 32-bit heap overflow
size_t new_heap_size = (__freetop - __freebase + sz + 4095) & ~4095;
// size_t new_heap_size = (__freetop - __freebase + sz + 4095) & ~4095;
size_t new_heap_size = (sz + sz / 5 + 4095) & ~4095; // 20% reserved
//statistics
wtalloc_stat.sysalloc_calls++;
if (new_heap_size > wtalloc_stat.malloc_max) wtalloc_stat.sysalloc_max = new_heap_size;
wtalloc_stat.sysalloc_sum += new_heap_size;
 
 
//хвост сунуть в свободные, а фритоп и базу перености на новый кусок
ptr = sysmalloc(new_heap_size); // rounded 4k
//TRACE2("call systemalloc(%d) returned %x\n", new_heap_size, ptr);
133,7 → 168,8
if (__firstfree)
__firstfree->prev = newnode;
__firstfree = newnode;
__crtfreeblocks++;
wtalloc_stat.crtfreeblocks++;
wtalloc_stat.freeblocks_sum += newnode->size;
//TRACE2("alloc(%d) add tail %d to freenode", sz, newnode->size);
//TRACE1(".tail [%x]\n", newnode);
}
149,6 → 185,18
__freebase += sz;
//TRACE1("__freebase [%x]\n", __freebase);
 
// check list availability
/*
int maxfree = 0;
for (fndnode = __firstfree; fndnode; fndnode = fndnode->next)
{
if (fndnode->size > maxfree) maxfree = fndnode->size;
}
 
TRACE2("alloc(%d) from freebase, maxfree = %d,", sz, maxfree);
TRACE1(" freelist len = %u \n", wtalloc_stat.crtfreeblocks);
*/
return ptr;
}
 
156,6 → 204,8
{
if (!ptr) return;
 
//TRACE1("free() to freenode, sized %d\n", ((struct hdrused*)((char*)ptr - 8))->size);
 
#ifndef NDEBUG
if (((struct hdrused*)((char*)ptr - 8))->mark != c_used)
{
166,13 → 216,83
struct hdrfree *newnode = (struct hdrfree*)((char*)ptr - 8);
newnode->mark = c_free;
//size stays
newnode->next = NULL;
newnode->prev = NULL;
 
// experimental - try to merge, if adjanced from bottom is also freeblock
int reorganized = 0;
struct hdrfree *higher;
{
struct hdrfree *p1;
higher = NULL;
for (p1 = __firstfree; p1; p1 = p1->next)
{
higher = (struct hdrfree *)((char*)p1 + p1->size);
if (higher == newnode) break;
}
if (p1) // yes, it is
{
wtalloc_stat.freeblocks_sum += newnode->size;
p1->size += newnode->size;
// p1->prev, p1->next already OK
newnode->mark = 0; // for safety
newnode = p1; // continue optimization
//TRACE2("free block merged w/bottom sized %u bytes, list len %u\n", p1->size, wtalloc_stat.crtfreeblocks);
reorganized = 1;
}
}
 
 
/* removed, as very seldom succeeds */
// experimental - try to merge, if adjanced from top is also freeblock
higher = (struct hdrfree *)((char*)newnode + newnode->size);
// dont work - we try to read after our memory
// if ((char*)higher < (char*)__freetop && // saves from reading out of our memory
// higher->mark == c_free) // only suspisious, must be in list
{
struct hdrfree *p1;
for (p1 = __firstfree; p1 && p1 != higher; p1 = p1->next);
if (p1) // yes, it is
{
if (newnode->next || newnode->prev) // optimized 1st stage, must remove from list and readd later
{
wtalloc_stat.crtfreeblocks--;
wtalloc_stat.freeblocks_sum -= newnode->size;
if (newnode->next)
newnode->next->prev = newnode->prev;
if (newnode->prev)
newnode->prev->next = newnode->next;
else
__firstfree = newnode->next;
}
wtalloc_stat.freeblocks_sum += newnode->size;
newnode->size += higher->size;
newnode->prev = higher->prev;
newnode->next = higher->next;
higher->mark = 0; // for safety
if (higher->next)
higher->next->prev = newnode;
if (higher->prev)
higher->prev->next = newnode;
else
__firstfree = newnode;
//TRACE1("free block merged w/top\n", 0);
reorganized = 1;
}
}
 
if (reorganized) return; // experimental reorganized do all work
//TRACE1("free block added\n", 0);
wtalloc_stat.crtfreeblocks++;
wtalloc_stat.freeblocks_sum += newnode->size;
 
newnode->next = __firstfree;
newnode->prev = NULL;
if (__firstfree)
__firstfree->prev = newnode;
__firstfree = newnode;
__crtfreeblocks++;
//TRACE1("free to freenode\n", 0);
}
 
 
192,10 → 312,21
 
if (oldptr->size - 8 >= sz) return ptr; // enough room in this block, ex from freelist
/* experimental growth last block */
int growth = (oldptr->size + sz + 15) & ~15;
if ((char*)oldptr + oldptr->size == __freebase &&
__freetop - __freebase + oldptr->size >= growth ) // we at top, can grow up
{
wtalloc_stat.malloc_sum += growth - oldptr->size;
__freebase += growth - oldptr->size;
oldptr->size = growth;
return ptr;
}
void *newptr = wtmalloc(sz);
if (newptr)
{
memcpy(newptr, (char*)oldptr +8, oldptr->size -8); // why -8 dont fail test?!?
memcpy(newptr, (char*)oldptr +8, oldptr->size -8); // why forgeting -8 dont fail test?!?
wtfree((char*)oldptr +8);
return newptr;
}
237,14 → 368,25
return 0;
}
}
if (cnt != __crtfreeblocks)
if (cnt != wtalloc_stat.crtfreeblocks)
{
TRACE1("allocated memory freelist check fail, length must be = %u\n", __crtfreeblocks);
TRACE2("allocated memory freelist check fail, length must be = %u but is %u\n", wtalloc_stat.crtfreeblocks, cnt);
return 0;
}
return 1;
}
 
void wtmalloc_freelist_print()
{
struct hdrfree *ptr = __firstfree;
for(;ptr; ptr = ptr->next)
{
TRACE2("(%x[%u])", ptr, ptr->size);
}
TRACE1("\n", 0);
}
 
int wtmalloc_poiner_check(void *ptr)
//контроль указателя - mark OK == 1
{
255,3 → 397,14
}
return 1;
}
 
void wtdump_alloc_stats()
{
TRACE1("----Watermark allocator stats:----\n", 0);
TRACE2("allocated %u calls, max of %u bytes\n", wtalloc_stat.malloc_calls, wtalloc_stat.malloc_max);
TRACE2("total %u bytes, average call %u bytes\n", wtalloc_stat.malloc_sum, wtalloc_stat.malloc_sum / wtalloc_stat.malloc_calls);
TRACE1("SYSTEM:\n", 0);
TRACE2("allocated %u calls, max of %u bytes\n", wtalloc_stat.sysalloc_calls, wtalloc_stat.sysalloc_max);
TRACE2("total %u bytes, average call %u bytes\n", wtalloc_stat.sysalloc_sum, wtalloc_stat.sysalloc_sum / wtalloc_stat.sysalloc_calls);
TRACE2("free list %u bytes, length %u chunks\n", wtalloc_stat.freeblocks_sum, wtalloc_stat.crtfreeblocks);
}
/programs/develop/ktcc/trunk/libctest/wtalloc.c
10,6 → 10,7
extern void* wtcalloc (size_t num, size_t size);
extern int wtmalloc_freelist_check();
extern int wtmalloc_poiner_check(void *ptr);
extern void wtdump_alloc_stats();
 
#ifdef __GNUC__
void* sysmalloc(size_t sz)
20,7 → 21,7
 
 
 
#define NUMPTR 30000
#define NUMPTR 10000
 
char *pointers[NUMPTR];
char values[NUMPTR];
59,7 → 60,7
// test allocation
for (i = 0; i < NUMPTR; i++)
{
sz = rand() % 1024;
sz = rand() % 4200;
pointers[i] = wtmalloc(sz);
sizes[i] = sz;
values[i] = sz % 256;
89,7 → 90,7
{
if (pointers[i]) continue;
sz = rand() % 1024;
sz = rand() % 4200;
pointers[i] = wtmalloc(sz);
sizes[i] = sz;
values[i] = sz % 256;
102,8 → 103,9
// test realloc
for (i = 0; i < NUMPTR; i++)
{
sz = rand() % 1024;
sz = rand() % 4200;
pointers[i] = wtrealloc(pointers[i], sz);
sizes[i] = sz;
memset(pointers[i], values[i], sz);
}
120,8 → 122,10
}
assert(wtmalloc_freelist_check());
 
printf("tests all OK\n");
wtdump_alloc_stats();
printf("\ntests all OK\n");
return 0;
 
}