parent
921fbfbc21
commit
652ea85a39
|
@ -1,2 +1,2 @@
|
|||
text (code + rodata) data bss dec hex filename
|
||||
54224 (45672 + 8552) 328 9820 64372 fb74 rtthread.elf
|
||||
67240 (58320 + 8920) 408 10168 77816 12ff8 rtthread.elf
|
||||
|
|
|
@ -38,7 +38,7 @@ PLATFORM_PATH := $(BSP_PATH)/AE210P
|
|||
ARCH_SEL_PATH := $(ARCH_PATH)/nds32
|
||||
CONFIG_PATH := $(PLATFORM_PATH)
|
||||
BOARD_PATH := $(PLATFORM_PATH)/board
|
||||
LIBC_PATH := $(PLATFORM_PATH)/libc
|
||||
#LIBC_PATH := $(PLATFORM_PATH)/libc
|
||||
LDSCRIPT := $(BOARD_PATH)/ae210p.ld
|
||||
CONFIG_H := $(CONFIG_PATH)/config.h
|
||||
PLATFORM_DEF := -DAE210P
|
||||
|
@ -63,8 +63,6 @@ INCLUDE_PATH := \
|
|||
-I$(BOARD_PATH) \
|
||||
-I$(DRIVERS_PATH) \
|
||||
-I$(CLI_PATH) \
|
||||
-I$(LIBC_PATH) \
|
||||
-I${PLATFORM_PATH}/include \
|
||||
-I$(COMPONENTS_DRVINC_PATH) \
|
||||
-I$(COMPONENTS_DRVINC_DRV_PATH) \
|
||||
-I$(COMPONENTS_INIT_PATH)
|
||||
|
@ -86,7 +84,7 @@ CFLAGS := \
|
|||
$(PLATFORM_DEF) \
|
||||
$(OS_DEF) \
|
||||
$(SMALL_HEAP_DEF) \
|
||||
-fno-builtin -fomit-frame-pointer -funroll-loops -nostdlib \
|
||||
-fno-builtin -fomit-frame-pointer -funroll-loops \
|
||||
-fno-strict-aliasing -ffunction-sections \
|
||||
$(CMODEL) \
|
||||
$(OPTIM) \
|
||||
|
@ -213,25 +211,25 @@ DRIVER_SRC := \
|
|||
$(COMPONENTS_DRV_PATH)/serial/serial.c
|
||||
# $(PLATFORM_PATH)/driver/dma/dmad.c
|
||||
|
||||
LIBC_SRC := \
|
||||
$(LIBC_PATH)/stdio/fgets.c \
|
||||
$(LIBC_PATH)/stdio/fputs.c \
|
||||
$(LIBC_PATH)/stdio/fprintf.c \
|
||||
$(LIBC_PATH)/stdio/do_printf.c \
|
||||
$(LIBC_PATH)/stdio/printf.c \
|
||||
$(LIBC_PATH)/string/memcpy.c \
|
||||
$(LIBC_PATH)/string/memmove.c \
|
||||
$(LIBC_PATH)/string/memset.c \
|
||||
$(LIBC_PATH)/string/strcat.c \
|
||||
$(LIBC_PATH)/string/strcasecmp.c \
|
||||
$(LIBC_PATH)/string/strcmp.c \
|
||||
$(LIBC_PATH)/string/strcpy.c \
|
||||
$(LIBC_PATH)/string/strdup.c \
|
||||
$(LIBC_PATH)/string/strlen.c \
|
||||
$(LIBC_PATH)/string/strstr.c \
|
||||
$(LIBC_PATH)/string/strupr.c \
|
||||
$(LIBC_PATH)/string/wchar.c \
|
||||
$(LIBC_PATH)/stdlib/qsort.c
|
||||
#LIBC_SRC := \
|
||||
# $(LIBC_PATH)/stdio/fgets.c \
|
||||
# $(LIBC_PATH)/stdio/fputs.c \
|
||||
# $(LIBC_PATH)/stdio/fprintf.c \
|
||||
# $(LIBC_PATH)/stdio/do_printf.c \
|
||||
# $(LIBC_PATH)/stdio/printf.c \
|
||||
# $(LIBC_PATH)/string/memcpy.c \
|
||||
# $(LIBC_PATH)/string/memmove.c \
|
||||
# $(LIBC_PATH)/string/memset.c \
|
||||
# $(LIBC_PATH)/string/strcat.c \
|
||||
# $(LIBC_PATH)/string/strcasecmp.c \
|
||||
# $(LIBC_PATH)/string/strcmp.c \
|
||||
# $(LIBC_PATH)/string/strcpy.c \
|
||||
# $(LIBC_PATH)/string/strdup.c \
|
||||
# $(LIBC_PATH)/string/strlen.c \
|
||||
# $(LIBC_PATH)/string/strstr.c \
|
||||
# $(LIBC_PATH)/string/strupr.c \
|
||||
# $(LIBC_PATH)/string/wchar.c \
|
||||
# $(LIBC_PATH)/stdlib/qsort.c
|
||||
|
||||
#LIBC_FILE_SRC := \
|
||||
# $(LIBC_PATH)/stdio/file.c \
|
||||
|
@ -251,8 +249,8 @@ SRCS := \
|
|||
${RTOS_SRC} \
|
||||
${DRIVER_SRC} \
|
||||
${CLI_SRC} \
|
||||
${APP_SRCS} \
|
||||
${LIBC_SRC}
|
||||
${APP_SRCS} #\
|
||||
# ${LIBC_SRC}
|
||||
|
||||
ALL_C_SRCS := ${SRCS}
|
||||
ALL_AS_SRCS += ${BOOT_SRC}
|
||||
|
|
|
@ -90,21 +90,21 @@ void rt_init_thread_entry(void* parameter)
|
|||
#endif /* #ifdef RT_USING_RTGUI */
|
||||
}
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
rt_thread_t test_thread[2];
|
||||
|
||||
void rt_test_thread_entry(void *parameter)
|
||||
{
|
||||
uint32_t num = (uint32_t)parameter;
|
||||
uint32_t schedule_times = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
DEBUG(1, 0, "%d:%d\r\n", num, schedule_times++);
|
||||
rt_thread_delay(1);
|
||||
}
|
||||
}
|
||||
//#include "debug.h"
|
||||
//
|
||||
//rt_thread_t test_thread[2];
|
||||
//
|
||||
//void rt_test_thread_entry(void *parameter)
|
||||
//{
|
||||
// uint32_t num = (uint32_t)parameter;
|
||||
// uint32_t schedule_times = 0;
|
||||
//
|
||||
// while (1)
|
||||
// {
|
||||
// DEBUG(1, 0, "%d:%d\r\n", num, schedule_times++);
|
||||
// rt_thread_delay(1);
|
||||
// }
|
||||
//}
|
||||
|
||||
int rt_application_init(void)
|
||||
{
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
#ifndef __CTYPE_H__
|
||||
#define __CTYPE_H__
|
||||
|
||||
static inline int islower(int c)
|
||||
{
|
||||
return c >= 'a' && c <= 'z';
|
||||
}
|
||||
|
||||
static inline int isupper(int c)
|
||||
{
|
||||
return c >= 'A' && c <= 'Z';
|
||||
}
|
||||
|
||||
static inline int isalpha(int c)
|
||||
{
|
||||
return islower(c) || isupper(c);
|
||||
}
|
||||
|
||||
static inline int isdigit(int c)
|
||||
{
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
static inline int isalnum(int c)
|
||||
{
|
||||
return isalpha(c) || isdigit(c);
|
||||
}
|
||||
|
||||
static inline int isblank(int c)
|
||||
{
|
||||
return c == ' ' || c == '\t';
|
||||
}
|
||||
|
||||
static inline int isspace(int c)
|
||||
{
|
||||
return c == ' ';
|
||||
}
|
||||
|
||||
static inline int isxdigit(int c)
|
||||
{
|
||||
return (c >= '0' && c <= '9') ||
|
||||
(c >= 'a' && c <= 'z') ||
|
||||
(c >= 'A' && c <= 'Z');
|
||||
}
|
||||
|
||||
// static inline int isascii(int c)
|
||||
// static inline int iscntrl(int c)
|
||||
// static inline int isgraph(int c)
|
||||
// static inline int isprint(int c)
|
||||
// static inline int ispunct(int c)
|
||||
#endif /* __CTYPE_H__ */
|
|
@ -1,20 +0,0 @@
|
|||
#include "../library/ndsvfs/include/ndsvfs.h"
|
||||
|
||||
struct dirent {
|
||||
|
||||
int d_cnt;
|
||||
int d_ino;
|
||||
int d_off;
|
||||
char d_name[256];
|
||||
};
|
||||
|
||||
struct dir {
|
||||
|
||||
int d_cnt;
|
||||
int d_off;
|
||||
NDSVFS_FILE *d_file;
|
||||
struct dirent *d_dirent;
|
||||
NDSVFS_DENTRY *vde_list;
|
||||
NDSVFS_DENTRY *vde_head;
|
||||
};
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
#ifndef _STDINT_H
|
||||
#include <stdint.h>
|
||||
#if 0
|
||||
#ifndef __INTTYPES_H__
|
||||
#define __INTTYPES_H__
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned long uint32_t;
|
||||
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed long int32_t;
|
||||
|
||||
typedef long intptr_t;
|
||||
typedef unsigned long uintptr_t;
|
||||
#endif
|
||||
#endif
|
||||
#endif /* __INTTYPES_H__ */
|
|
@ -1,324 +0,0 @@
|
|||
#ifndef __LIST_H__
|
||||
#define __LIST_H__
|
||||
|
||||
/*
|
||||
* These are non-NULL pointers that will result in page faults
|
||||
* under normal circumstances, used to verify that nobody uses
|
||||
* non-initialized list entries.
|
||||
*/
|
||||
#define LIST_POISON1 ((void*) 0x00100100)
|
||||
#define LIST_POISON2 ((void*) 0x00200200)
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE*)0)->MEMBER)
|
||||
#endif
|
||||
|
||||
#define container_of(ptr, type, member) ( { \
|
||||
const typeof(((type*)0)->member ) *__mptr = (ptr); \
|
||||
(type*)((char*)__mptr - offsetof(type,member) );})
|
||||
|
||||
|
||||
/*
|
||||
* Simple doubly linked list implementation.
|
||||
*
|
||||
* Some of the internal functions ("__xxx") are useful when
|
||||
* manipulating whole lists rather than single entries, as
|
||||
* sometimes we already know the next/prev entries and we can
|
||||
* generate better code by using them directly rather than
|
||||
* using the generic single-entry routines.
|
||||
*/
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
};
|
||||
|
||||
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||
|
||||
#define LIST_HEAD(name) \
|
||||
struct list_head name = LIST_HEAD_INIT(name)
|
||||
|
||||
#define INIT_LIST_HEAD(ptr) do { \
|
||||
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Insert a new entry between two known consecutive entries.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __list_add(struct list_head *new,
|
||||
struct list_head *prev,
|
||||
struct list_head *next)
|
||||
{
|
||||
next->prev = new;
|
||||
new->next = next;
|
||||
new->prev = prev;
|
||||
prev->next = new;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it after
|
||||
*
|
||||
* Insert a new entry after the specified head.
|
||||
* This is good for implementing stacks.
|
||||
*/
|
||||
static inline void list_add(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head, head->next);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add_tail - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it before
|
||||
*
|
||||
* Insert a new entry before the specified head.
|
||||
* This is useful for implementing queues.
|
||||
*/
|
||||
static inline void list_add_tail(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head->prev, head);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Delete a list entry by making the prev/next entries
|
||||
* point to each other.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __list_del(struct list_head * prev, struct list_head * next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del - deletes entry from list.
|
||||
* @entry: the element to delete from the list.
|
||||
* Note: list_empty on entry does not return true after this, the entry is
|
||||
* in an undefined state.
|
||||
*/
|
||||
static inline void list_del(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
entry->next = LIST_POISON1;
|
||||
entry->prev = LIST_POISON2;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del_init - deletes entry from list and reinitialize it.
|
||||
* @entry: the element to delete from the list.
|
||||
*/
|
||||
static inline void list_del_init(struct list_head *entry) {
|
||||
|
||||
__list_del(entry->prev, entry->next);
|
||||
INIT_LIST_HEAD(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_move - delete from one list and add as another's head
|
||||
* @list: the entry to move
|
||||
* @head: the head that will precede our entry
|
||||
*/
|
||||
static inline void list_move(struct list_head *list, struct list_head *head) {
|
||||
|
||||
__list_del(list->prev, list->next);
|
||||
list_add(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_move_tail - delete from one list and add as another's tail
|
||||
* @list: the entry to move
|
||||
* @head: the head that will follow our entry
|
||||
*/
|
||||
static inline void list_move_tail(struct list_head *list, struct list_head *head) {
|
||||
|
||||
__list_del(list->prev, list->next);
|
||||
list_add_tail(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_empty - tests whether a list is empty
|
||||
* @head: the list to test.
|
||||
*/
|
||||
static inline int list_empty(const struct list_head *head)
|
||||
{
|
||||
return head->next == head;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_empty_careful - tests whether a list is
|
||||
* empty _and_ checks that no other CPU might be
|
||||
* in the process of still modifying either member
|
||||
*
|
||||
* NOTE: using list_empty_careful() without synchronization
|
||||
* can only be safe if the only activity that can happen
|
||||
* to the list entry is list_del_init(). Eg. it cannot be used
|
||||
* if another CPU could re-list_add() it.
|
||||
*
|
||||
* @head: the list to test.
|
||||
*/
|
||||
static inline int list_empty_careful(const struct list_head *head)
|
||||
{
|
||||
struct list_head *next = head->next;
|
||||
return (next == head) && (next == head->prev);
|
||||
}
|
||||
|
||||
static inline void __list_splice(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct list_head *first = list->next;
|
||||
struct list_head *last = list->prev;
|
||||
struct list_head *at = head->next;
|
||||
|
||||
first->prev = head;
|
||||
head->next = first;
|
||||
|
||||
last->next = at;
|
||||
at->prev = last;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice - join two lists
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*/
|
||||
static inline void list_splice(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list))
|
||||
__list_splice(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice_init - join two lists and reinitialise the emptied list.
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*
|
||||
* The list at @list is reinitialised
|
||||
*/
|
||||
static inline void list_splice_init(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list)) {
|
||||
__list_splice(list, head);
|
||||
INIT_LIST_HEAD(list);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int list_swap(struct list_head *a, struct list_head *b, struct list_head *list)
|
||||
{
|
||||
if (a->next == list || b->prev == list)
|
||||
return -1;
|
||||
|
||||
list_del(a);
|
||||
list_add(a, b);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* list_entry - get the struct for this entry
|
||||
* @ptr: the &struct list_head pointer.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_entry(ptr, type, member) \
|
||||
container_of(ptr, type, member)
|
||||
|
||||
/**
|
||||
* list_for_each - iterate over a list
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_prev - iterate over a list backwards
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_prev(pos, head) \
|
||||
for (pos = (head)->prev; pos != (head); pos = pos->prev)
|
||||
|
||||
/**
|
||||
* list_for_each_safe - iterate over a list safe against removal of list entry
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @n: another &struct list_head to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_safe(pos, n, head) \
|
||||
for (pos = (head)->next, n = pos->next; pos != (head); pos = n, n = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_entry - iterate over list of given type
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry(pos, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member); &pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_reverse - iterate backwards over list of given type.
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_reverse(pos, head, member) \
|
||||
for (pos = list_entry((head)->prev, typeof(*pos), member); &pos->member != (head); \
|
||||
pos = list_entry(pos->member.prev, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_prepare_entry - prepare a pos entry for use as a start point in
|
||||
* list_for_each_entry_continue
|
||||
* @pos: the type * to use as a start point
|
||||
* @head: the head of the list
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_prepare_entry(pos, head, member) \
|
||||
((pos) ? : list_entry(head, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_continue - iterate over list of given type
|
||||
* continuing after existing point
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_continue(pos, head, member) \
|
||||
for (pos = list_entry(pos->member.next, typeof(*pos), member); &pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_safe(pos, n, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member), \
|
||||
n = list_entry(pos->member.next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.next, typeof(*n), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_reverse_safe - iterate over list of given type safe against removal of list entry
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_reverse_safe(pos, n, head, member) \
|
||||
for (pos = list_entry((head)->prev, typeof(*pos), member), \
|
||||
n = list_entry(pos->member.prev, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.prev, typeof(*n), member))
|
||||
|
||||
#endif /* __LIST_H__ */
|
|
@ -1,130 +0,0 @@
|
|||
/* Copyright (C) 1989, 1997, 1998, 1999, 2000, 2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/*
|
||||
* ISO C Standard: 7.15 Variable arguments <stdarg.h>
|
||||
*/
|
||||
|
||||
#ifndef _STDARG_H
|
||||
#ifndef _ANSI_STDARG_H_
|
||||
#ifndef __need___va_list
|
||||
#define _STDARG_H
|
||||
#define _ANSI_STDARG_H_
|
||||
#endif /* not __need___va_list */
|
||||
#undef __need___va_list
|
||||
|
||||
/* Define __gnuc_va_list. */
|
||||
|
||||
#ifndef __GNUC_VA_LIST
|
||||
#define __GNUC_VA_LIST
|
||||
typedef __builtin_va_list __gnuc_va_list;
|
||||
#endif
|
||||
|
||||
/* Define the standard macros for the user,
|
||||
if this invocation was from the user program. */
|
||||
#ifdef _STDARG_H
|
||||
|
||||
#define va_start(v,l) __builtin_va_start(v,l)
|
||||
#define va_end(v) __builtin_va_end(v)
|
||||
#define va_arg(v,l) __builtin_va_arg(v,l)
|
||||
#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
#define va_copy(d,s) __builtin_va_copy(d,s)
|
||||
#endif
|
||||
#define __va_copy(d,s) __builtin_va_copy(d,s)
|
||||
|
||||
/* Define va_list, if desired, from __gnuc_va_list. */
|
||||
/* We deliberately do not define va_list when called from
|
||||
stdio.h, because ANSI C says that stdio.h is not supposed to define
|
||||
va_list. stdio.h needs to have access to that data type,
|
||||
but must not use that name. It should use the name __gnuc_va_list,
|
||||
which is safe because it is reserved for the implementation. */
|
||||
|
||||
#ifdef _HIDDEN_VA_LIST /* On OSF1, this means varargs.h is "half-loaded". */
|
||||
#undef _VA_LIST
|
||||
#endif
|
||||
|
||||
#ifdef _BSD_VA_LIST
|
||||
#undef _BSD_VA_LIST
|
||||
#endif
|
||||
|
||||
#if defined(__svr4__) || (defined(_SCO_DS) && !defined(__VA_LIST))
|
||||
/* SVR4.2 uses _VA_LIST for an internal alias for va_list,
|
||||
so we must avoid testing it and setting it here.
|
||||
SVR4 uses _VA_LIST as a flag in stdarg.h, but we should
|
||||
have no conflict with that. */
|
||||
#ifndef _VA_LIST_
|
||||
#define _VA_LIST_
|
||||
#ifdef __i860__
|
||||
#ifndef _VA_LIST
|
||||
#define _VA_LIST va_list
|
||||
#endif
|
||||
#endif /* __i860__ */
|
||||
typedef __gnuc_va_list va_list;
|
||||
#ifdef _SCO_DS
|
||||
#define __VA_LIST
|
||||
#endif
|
||||
#endif /* _VA_LIST_ */
|
||||
#else /* not __svr4__ || _SCO_DS */
|
||||
|
||||
/* The macro _VA_LIST_ is the same thing used by this file in Ultrix.
|
||||
But on BSD NET2 we must not test or define or undef it.
|
||||
(Note that the comments in NET 2's ansi.h
|
||||
are incorrect for _VA_LIST_--see stdio.h!) */
|
||||
#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(WINNT)
|
||||
/* The macro _VA_LIST_DEFINED is used in Windows NT 3.5 */
|
||||
#ifndef _VA_LIST_DEFINED
|
||||
/* The macro _VA_LIST is used in SCO Unix 3.2. */
|
||||
#ifndef _VA_LIST
|
||||
/* The macro _VA_LIST_T_H is used in the Bull dpx2 */
|
||||
#ifndef _VA_LIST_T_H
|
||||
/* The macro __va_list__ is used by BeOS. */
|
||||
#ifndef __va_list__
|
||||
typedef __gnuc_va_list va_list;
|
||||
#endif /* not __va_list__ */
|
||||
#endif /* not _VA_LIST_T_H */
|
||||
#endif /* not _VA_LIST */
|
||||
#endif /* not _VA_LIST_DEFINED */
|
||||
#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__))
|
||||
#define _VA_LIST_
|
||||
#endif
|
||||
#ifndef _VA_LIST
|
||||
#define _VA_LIST
|
||||
#endif
|
||||
#ifndef _VA_LIST_DEFINED
|
||||
#define _VA_LIST_DEFINED
|
||||
#endif
|
||||
#ifndef _VA_LIST_T_H
|
||||
#define _VA_LIST_T_H
|
||||
#endif
|
||||
#ifndef __va_list__
|
||||
#define __va_list__
|
||||
#endif
|
||||
|
||||
#endif /* not _VA_LIST_, except on certain systems */
|
||||
|
||||
#endif /* not __svr4__ */
|
||||
|
||||
#endif /* _STDARG_H */
|
||||
|
||||
#endif /* not _ANSI_STDARG_H_ */
|
||||
#endif /* not _STDARG_H */
|
|
@ -1,5 +0,0 @@
|
|||
#ifndef __STDDEF_H__
|
||||
#define __STDDEF_H__
|
||||
|
||||
typedef unsigned long size_t;
|
||||
#endif /* __STDDEF_H__ */
|
|
@ -1,64 +0,0 @@
|
|||
#ifndef __STDIO_H__
|
||||
#define __STDIO_H__
|
||||
|
||||
#include <stdarg.h> /* va_list, va_arg() */
|
||||
#include <stddef.h> /* size_t */
|
||||
#include <stdlib.h>
|
||||
//#include <dirent.h>
|
||||
// FIXME: find a right place to define the following things
|
||||
// constants
|
||||
typedef int fpos_t;
|
||||
#define FSEEK_SET 0 // origin is beginning of the file
|
||||
#define FSEEK_CUR 1 // origin is current position
|
||||
#define FSEEK_END 2 // origin is end of the file
|
||||
|
||||
typedef unsigned long FILE;
|
||||
typedef int time_t;
|
||||
struct stat {
|
||||
int st_dev; /* ID of device containing file */
|
||||
int st_ino; /* inode number */
|
||||
int st_mode; /* protection */
|
||||
int st_size; /* total size, in bytes */
|
||||
int st_blksize; /* blocksize for file system I/O */
|
||||
int st_blocks; /* number of 512B blocks allocated */
|
||||
time_t st_atime; /* time of last access */
|
||||
time_t st_mtime; /* time of last modification */
|
||||
time_t st_ctime; /* time of last status change */
|
||||
};
|
||||
|
||||
#define stdin ((void*)0)
|
||||
#define stdout ((void*)0)
|
||||
#define stderr ((void*)0)
|
||||
#define EOF (-1)
|
||||
|
||||
int vsprintf(char *buffer, const char *fmt, va_list args);
|
||||
int sprintf(char *buffer, const char *fmt, ...);
|
||||
int vprintf(const char *fmt, va_list args);
|
||||
int printf(const char *fmt, ...);
|
||||
int fprintf(FILE *stream, const char *format, ...);
|
||||
|
||||
int fgetc(FILE *stream);
|
||||
char *fgets(char *s, int size, FILE *stream);
|
||||
int getc(FILE *stream);
|
||||
int getchar(void);
|
||||
char *gets(char *s);
|
||||
int ungetc(int c, FILE *stream);
|
||||
|
||||
int fputc(int c, FILE *stream);
|
||||
int fputs(const char *s, FILE *stream);
|
||||
int putc(int c, FILE *stream);
|
||||
int putchar(int c);
|
||||
int puts(const char *s);
|
||||
FILE *fopen(const char *path, const char *mode);
|
||||
FILE *fdopen(int fd, const char *mode);
|
||||
FILE *freopen(const char *path, const char *mode, FILE *stream);
|
||||
int fclose(FILE *fp);
|
||||
|
||||
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
struct dir *opendir(const char *path);
|
||||
struct dirent *readdir(struct dir *dirp);
|
||||
int closedir(struct dir *dirp);
|
||||
int fstat(FILE* fd, struct stat *buf);
|
||||
|
||||
#endif /* __STDIO_H__ */
|
|
@ -1,70 +0,0 @@
|
|||
#ifndef __STDLIB_H__
|
||||
#define __STDLIB_H__
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void*)0)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_OS_UCOS_II) || defined(CONFIG_OS_UCOS_III)
|
||||
#include "kmem.h"
|
||||
static inline void *malloc(size_t size)
|
||||
{
|
||||
return kmalloc(size);
|
||||
}
|
||||
|
||||
static inline void free(void *ptr)
|
||||
{
|
||||
return kfree(ptr);
|
||||
}
|
||||
#elif defined(CONFIG_OS_FREERTOS)
|
||||
extern void *pvPortMalloc( size_t xWantedSize );
|
||||
extern void vPortFree( void *pv );
|
||||
#define malloc pvPortMalloc
|
||||
#define free vPortFree
|
||||
#elif defined(CONFIG_OS_THREADX)
|
||||
#include "kmem.h"
|
||||
static inline void *malloc(size_t size)
|
||||
{
|
||||
return kmalloc(size);
|
||||
}
|
||||
|
||||
static inline void free(void *ptr)
|
||||
{
|
||||
return kfree(ptr);
|
||||
}
|
||||
#elif defined(CONFIG_OS_RTTHREAD)
|
||||
#include "rtdef.h"
|
||||
#include "rtthread.h"
|
||||
#define malloc rt_malloc
|
||||
#define free rt_Free
|
||||
#else
|
||||
# error "No valid OS is defined!"
|
||||
#endif
|
||||
static inline void *calloc(size_t nmemb, size_t size)
|
||||
{
|
||||
int i = nmemb * size;
|
||||
unsigned char *ret = malloc(i);
|
||||
|
||||
while (i >= 0)
|
||||
ret[--i] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void *realloc(void *ptr, size_t size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void exit(int status)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void abort(void)
|
||||
{
|
||||
}
|
||||
|
||||
void qsort(void *base, size_t nel, size_t width, int (*compar)(const void *, const void *));
|
||||
extern int atoi(const char *__nptr);
|
||||
#endif /* __STDLIB_H__ */
|
|
@ -1,51 +0,0 @@
|
|||
#ifndef __STRING_H__
|
||||
#define __STRING_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
extern void *memcpy(void *dest, const void *src, size_t n);
|
||||
extern void *memmove(void *dest, const void *src, size_t n);
|
||||
extern void *memset(void *s, int c, size_t n);
|
||||
extern void bzero(void *, size_t);
|
||||
|
||||
extern char *strcat(char *dest, const char *src);
|
||||
extern char *strncat(char *dest, const char *src, size_t n);
|
||||
|
||||
extern int strcasecmp(const char *s1, const char *s2);
|
||||
extern int strncasecmp(const char *s1, const char *s2, size_t n);
|
||||
|
||||
extern int strcmp(const char *s1, const char *s2);
|
||||
extern int strncmp(const char *s1, const char *s2, size_t n);
|
||||
|
||||
extern char *strcpy(char *dest, const void *src);
|
||||
extern char *strncpy(char *dest, const void *src, size_t n);
|
||||
|
||||
extern char *strdup(const char *s);
|
||||
extern char *strndup(const char *s, size_t n);
|
||||
extern size_t strlen(const char *s);
|
||||
extern size_t strnlen(const char *s, size_t maxlen);
|
||||
|
||||
extern char *strstr(const char *haystack, const char *needle);
|
||||
extern unsigned long int strtoul(const char *nptr, char **endptr, int base);
|
||||
|
||||
extern char *strupr(char *str);
|
||||
/* wchar_t */
|
||||
#ifndef WCHAR
|
||||
typedef unsigned short WCHAR;
|
||||
#endif // WCHAR
|
||||
|
||||
#ifndef wchar_t
|
||||
typedef unsigned short wchar_t;
|
||||
#endif // wchar
|
||||
|
||||
extern wchar_t *wcscat(wchar_t *str_dst, const wchar_t *str_src);
|
||||
extern int wcscmp(const wchar_t *string1, const wchar_t *string2);
|
||||
extern int wcsncmp(const wchar_t *string1, const wchar_t *string2, int count);
|
||||
extern wchar_t *wcscpy(wchar_t *str_dst, const wchar_t *str_src);
|
||||
extern wchar_t *wcsncpy(wchar_t *str_dst, const wchar_t *str_src, int count);
|
||||
extern int wcslen(const wchar_t *str);
|
||||
extern wchar_t *wcsupr(wchar_t *str);
|
||||
extern wchar_t *wcslwr(wchar_t *str);
|
||||
|
||||
|
||||
#endif /* __STRING_H__ */
|
|
@ -1,220 +0,0 @@
|
|||
#include "kmem.h"
|
||||
#include "slab.h"
|
||||
#include "debug.h"
|
||||
#include "hal.h"
|
||||
|
||||
static struct page_struct mem_map[MEM_LIMIT >> PG_SHIFT];
|
||||
|
||||
static intptr_t kmem_start;
|
||||
static intptr_t kmem_end;
|
||||
static intptr_t kmem_size;
|
||||
static intptr_t kmem_total_pages;
|
||||
static intptr_t kmem_free_pages;
|
||||
|
||||
static inline int pg_is_free(struct page_struct *page)
|
||||
{
|
||||
return page->flag & PG_FLAG_FREE;
|
||||
}
|
||||
|
||||
static inline void *pf_to_addr(intptr_t pg_idx)
|
||||
{
|
||||
return (void*)(kmem_start + (pg_idx << PG_SHIFT));
|
||||
}
|
||||
|
||||
static inline intptr_t addr_to_pf(void *addr)
|
||||
{
|
||||
return (intptr_t)(addr - kmem_start) >> PG_SHIFT;
|
||||
}
|
||||
|
||||
static inline void pg_flag_set(intptr_t start, intptr_t count, uint32_t flag)
|
||||
{
|
||||
while (count-- > 0)
|
||||
mem_map[start + count].flag |= flag;
|
||||
}
|
||||
|
||||
static inline void pg_flag_clr(intptr_t start, intptr_t count, uint32_t flag)
|
||||
{
|
||||
while (count-- > 0)
|
||||
mem_map[start + count].flag &= ~flag;
|
||||
}
|
||||
|
||||
struct page_struct *addr_to_pf_des(void *addr)
|
||||
{
|
||||
return &mem_map[addr_to_pf(addr)];
|
||||
}
|
||||
|
||||
int init_kmem(intptr_t start, intptr_t end)
|
||||
{
|
||||
extern char *_end;
|
||||
if((unsigned int)start < (unsigned int)&_end)
|
||||
KPANIC("start and _end are overlap. start:%08x, _end=%08x\n", start, &_end);
|
||||
kmem_start = start & PG_MASK;
|
||||
kmem_end = end & PG_MASK;
|
||||
kmem_size = kmem_end - kmem_start;
|
||||
|
||||
kmem_total_pages = kmem_size >> PG_SHIFT;
|
||||
kmem_free_pages = kmem_total_pages;
|
||||
|
||||
pg_flag_set(0, kmem_total_pages, PG_FLAG_FREE);
|
||||
|
||||
DEBUG(1, 0, "*************************************************\n");
|
||||
DEBUG(1, 0, "* Initializeing MM *\n");
|
||||
DEBUG(1, 0, "*************************************************\n");
|
||||
|
||||
DEBUG(1, 1, "Start:0x%08x End:0x%08x, Size:0x%08x(%dK), Pages:%d\n",
|
||||
kmem_start, kmem_end, kmem_size,
|
||||
kmem_size >> 10, kmem_total_pages);
|
||||
#ifdef CONFIG_KMEM_SLAB
|
||||
init_cache();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *alloc_pages(intptr_t pg_req_nr)
|
||||
{
|
||||
intptr_t pg_begin_idx = -1;
|
||||
intptr_t pg_found_nr = 0;
|
||||
intptr_t i = 0;
|
||||
|
||||
DEBUG(0, 1, "Requesting for %d/%d/%d pages\n",
|
||||
pg_req_nr, kmem_free_pages, kmem_total_pages);
|
||||
|
||||
if (kmem_free_pages < pg_req_nr)
|
||||
return (void*)0;
|
||||
|
||||
for (i = 0; i < kmem_total_pages; i++) {
|
||||
|
||||
if (!pg_is_free(&mem_map[i])) {
|
||||
|
||||
pg_begin_idx = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pg_begin_idx < 0) {
|
||||
|
||||
pg_begin_idx = i;
|
||||
pg_found_nr = 1;
|
||||
}
|
||||
else {
|
||||
pg_found_nr++;
|
||||
}
|
||||
|
||||
if (pg_found_nr == pg_req_nr) {
|
||||
|
||||
pg_flag_clr(pg_begin_idx, pg_req_nr, PG_FLAG_FREE);
|
||||
mem_map[pg_begin_idx].alloc_nr = pg_req_nr;
|
||||
|
||||
kmem_free_pages -= pg_req_nr;
|
||||
|
||||
DEBUG(0, 1, "return mem_map %d pages at [%d]:0x%08x\n",
|
||||
pg_req_nr, pg_begin_idx, (intptr_t)pf_to_addr(pg_begin_idx));
|
||||
|
||||
return pf_to_addr(pg_begin_idx);
|
||||
}
|
||||
}
|
||||
|
||||
return (void*)0;
|
||||
}
|
||||
|
||||
void *alloc_page(void)
|
||||
{
|
||||
return alloc_pages(1);
|
||||
}
|
||||
|
||||
void free_pages(void *addr)
|
||||
{
|
||||
intptr_t idx = addr_to_pf(addr);
|
||||
|
||||
KASSERT(!pg_is_free(&mem_map[idx]))
|
||||
|
||||
pg_flag_set(idx, mem_map[idx].alloc_nr, PG_FLAG_FREE);
|
||||
|
||||
DEBUG(0, 1, "0x:%08x, idx:%d, pages:%d, phy_addr:%08x\n",
|
||||
(intptr_t)addr, idx, mem_map[idx].alloc_nr,
|
||||
(intptr_t)pf_to_addr(idx));
|
||||
|
||||
kmem_free_pages += mem_map[idx].alloc_nr;
|
||||
mem_map[idx].alloc_nr = 0;
|
||||
}
|
||||
|
||||
void *kmalloc(intptr_t size)
|
||||
{
|
||||
void *addr = 0;
|
||||
intptr_t pg_req_nr = 0;
|
||||
int core_intl = 0;
|
||||
|
||||
core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS);
|
||||
|
||||
DEBUG(0, 1, "%d bytes at:", size);
|
||||
|
||||
#ifdef CONFIG_KMEM_USING_SLAB
|
||||
addr = kmem_cache_alloc_gen(size);
|
||||
if (addr) {
|
||||
|
||||
DEBUG(0, 0, " 0x%08x\n", (intptr_t)addr);
|
||||
hal_global_int_ctl(core_intl);
|
||||
return addr;
|
||||
}
|
||||
#endif
|
||||
size = (size + (PG_SIZE - 1)) & PG_MASK;
|
||||
pg_req_nr = size >> PG_SHIFT;
|
||||
|
||||
if (pg_req_nr <= kmem_free_pages) {
|
||||
|
||||
addr = alloc_pages(pg_req_nr);
|
||||
DEBUG(0, 0, " 0x%08x\n", (intptr_t)addr);
|
||||
}
|
||||
else {
|
||||
DEBUG(0, 0, "FAIL:(req:%d, free:%d)\n", pg_req_nr, kmem_free_pages);
|
||||
}
|
||||
|
||||
hal_global_int_ctl(core_intl);
|
||||
return addr;
|
||||
}
|
||||
|
||||
void kfree(void *addr)
|
||||
{
|
||||
int core_intl = 0;
|
||||
|
||||
core_intl = hal_global_int_ctl(HAL_DISABLE_INTERRUPTS);
|
||||
#ifdef CONFIG_KMEM_USING_SLAB
|
||||
struct page_struct *pg = addr_to_pf_des(addr);
|
||||
struct cache_struct *cp = GET_PAGE_CACHE(pg);
|
||||
|
||||
if (cp) {
|
||||
DEBUG(0, 1, "0x%08x\n", (intptr_t)addr);
|
||||
kmem_cache_free(cp, addr);
|
||||
|
||||
hal_global_int_ctl(core_intl);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
DEBUG(0, 1, "0x%08x\n", (intptr_t)addr);
|
||||
|
||||
free_pages(addr);
|
||||
hal_global_int_ctl(core_intl);
|
||||
}
|
||||
|
||||
void mem_dump_map(void)
|
||||
{
|
||||
intptr_t i;
|
||||
|
||||
DEBUG(1, 1, "*:free +: begin of allocated chunk, -:allocated\n");
|
||||
|
||||
for (i = 0; i < kmem_total_pages; i++) {
|
||||
|
||||
if (i%32 == 0)
|
||||
DEBUG(1, 0, "\n0x%08x\t: ", kmem_start + i * PG_SIZE);
|
||||
else if (i%8 == 0)
|
||||
DEBUG(1, 0, " ");
|
||||
|
||||
if (pg_is_free(&mem_map[i]))
|
||||
DEBUG(1, 0, "*");
|
||||
else if (mem_map[i].alloc_nr)
|
||||
DEBUG(1, 0, "+");
|
||||
else
|
||||
DEBUG(1, 0, "-");
|
||||
}
|
||||
|
||||
DEBUG(1, 0, "\n");
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
#ifndef __KMEM_H__
|
||||
#define __KMEM_H__
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#define PG_FLAG_FREE 0x00000001
|
||||
|
||||
|
||||
#ifdef CONFIG_PLAT_AE210P
|
||||
#include "ae210p_regs.h"
|
||||
#define PG_MASK 0xFFFFFF00
|
||||
#define PG_SHIFT 8
|
||||
#define PG_SIZE (1 << PG_SHIFT) //256Byte per page
|
||||
|
||||
/* 48MB ~ 112MB */
|
||||
#define MEM_START 0x00208000 //EDLM_BASEi+32K
|
||||
#define MEM_END 0x00210000 //EDLM_BASE+64K
|
||||
|
||||
|
||||
#elif defined( CONFIG_LATENCY_HEAP )
|
||||
#define PG_MASK 0xFFFFFFC0
|
||||
#define PG_SHIFT 6
|
||||
#define PG_SIZE (1 << PG_SHIFT)
|
||||
#define MEM_START 0x0C000
|
||||
#define MEM_END 0x10000
|
||||
#else
|
||||
#ifdef CONFIG_PLAT_AG101P_16MB
|
||||
#define PG_MASK 0xFFFFFF00
|
||||
#define PG_SHIFT 8
|
||||
#define PG_SIZE (1 << PG_SHIFT)
|
||||
|
||||
#ifdef CONFIG_SMALL_HEAP
|
||||
/* 6MB ~ 7MB*/
|
||||
#define MEM_START 0x00600000
|
||||
#else
|
||||
/* 3MB ~ 7MB*/
|
||||
#define MEM_START 0x00300000
|
||||
#endif
|
||||
#define MEM_END 0x00700000
|
||||
#else
|
||||
#define PG_MASK 0xFFFFF000
|
||||
#define PG_SHIFT 12
|
||||
#define PG_SIZE (1 << PG_SHIFT)
|
||||
|
||||
/* 48MB ~ 112MB */
|
||||
#define MEM_START 0x03000000
|
||||
#define MEM_END 0x07000000
|
||||
#endif
|
||||
#endif
|
||||
#define MEM_LIMIT ((MEM_END) - (MEM_START))
|
||||
|
||||
|
||||
struct page_struct {
|
||||
|
||||
struct list_head lru;
|
||||
uint32_t flag;
|
||||
intptr_t alloc_nr;
|
||||
};
|
||||
|
||||
extern int init_kmem(intptr_t start, intptr_t end);
|
||||
|
||||
extern void *alloc_pages(intptr_t pg_req_nr);
|
||||
extern void *alloc_page(void);
|
||||
extern void free_pages(void *addr);
|
||||
|
||||
extern void *kmalloc(intptr_t size);
|
||||
extern void kfree(void *addr);
|
||||
extern struct page_struct *addr_to_pf_des(void *addr);
|
||||
|
||||
extern void mem_dump_map(void);
|
||||
|
||||
#endif /* __KMEM_H__ */
|
|
@ -1,324 +0,0 @@
|
|||
#ifndef __LIST_H__
|
||||
#define __LIST_H__
|
||||
|
||||
/*
|
||||
* These are non-NULL pointers that will result in page faults
|
||||
* under normal circumstances, used to verify that nobody uses
|
||||
* non-initialized list entries.
|
||||
*/
|
||||
#define LIST_POISON1 ((void*) 0x00100100)
|
||||
#define LIST_POISON2 ((void*) 0x00200200)
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE*)0)->MEMBER)
|
||||
#endif
|
||||
|
||||
#define container_of(ptr, type, member) ( { \
|
||||
const typeof(((type*)0)->member ) *__mptr = (ptr); \
|
||||
(type*)((char*)__mptr - offsetof(type,member) );})
|
||||
|
||||
|
||||
/*
|
||||
* Simple doubly linked list implementation.
|
||||
*
|
||||
* Some of the internal functions ("__xxx") are useful when
|
||||
* manipulating whole lists rather than single entries, as
|
||||
* sometimes we already know the next/prev entries and we can
|
||||
* generate better code by using them directly rather than
|
||||
* using the generic single-entry routines.
|
||||
*/
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
};
|
||||
|
||||
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||
|
||||
#define LIST_HEAD(name) \
|
||||
struct list_head name = LIST_HEAD_INIT(name)
|
||||
|
||||
#define INIT_LIST_HEAD(ptr) do { \
|
||||
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Insert a new entry between two known consecutive entries.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __list_add(struct list_head *new,
|
||||
struct list_head *prev,
|
||||
struct list_head *next)
|
||||
{
|
||||
next->prev = new;
|
||||
new->next = next;
|
||||
new->prev = prev;
|
||||
prev->next = new;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it after
|
||||
*
|
||||
* Insert a new entry after the specified head.
|
||||
* This is good for implementing stacks.
|
||||
*/
|
||||
static inline void list_add(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head, head->next);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add_tail - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it before
|
||||
*
|
||||
* Insert a new entry before the specified head.
|
||||
* This is useful for implementing queues.
|
||||
*/
|
||||
static inline void list_add_tail(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head->prev, head);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Delete a list entry by making the prev/next entries
|
||||
* point to each other.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __list_del(struct list_head * prev, struct list_head * next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del - deletes entry from list.
|
||||
* @entry: the element to delete from the list.
|
||||
* Note: list_empty on entry does not return true after this, the entry is
|
||||
* in an undefined state.
|
||||
*/
|
||||
static inline void list_del(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
entry->next = LIST_POISON1;
|
||||
entry->prev = LIST_POISON2;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del_init - deletes entry from list and reinitialize it.
|
||||
* @entry: the element to delete from the list.
|
||||
*/
|
||||
static inline void list_del_init(struct list_head *entry) {
|
||||
|
||||
__list_del(entry->prev, entry->next);
|
||||
INIT_LIST_HEAD(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_move - delete from one list and add as another's head
|
||||
* @list: the entry to move
|
||||
* @head: the head that will precede our entry
|
||||
*/
|
||||
static inline void list_move(struct list_head *list, struct list_head *head) {
|
||||
|
||||
__list_del(list->prev, list->next);
|
||||
list_add(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_move_tail - delete from one list and add as another's tail
|
||||
* @list: the entry to move
|
||||
* @head: the head that will follow our entry
|
||||
*/
|
||||
static inline void list_move_tail(struct list_head *list, struct list_head *head) {
|
||||
|
||||
__list_del(list->prev, list->next);
|
||||
list_add_tail(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_empty - tests whether a list is empty
|
||||
* @head: the list to test.
|
||||
*/
|
||||
static inline int list_empty(const struct list_head *head)
|
||||
{
|
||||
return head->next == head;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_empty_careful - tests whether a list is
|
||||
* empty _and_ checks that no other CPU might be
|
||||
* in the process of still modifying either member
|
||||
*
|
||||
* NOTE: using list_empty_careful() without synchronization
|
||||
* can only be safe if the only activity that can happen
|
||||
* to the list entry is list_del_init(). Eg. it cannot be used
|
||||
* if another CPU could re-list_add() it.
|
||||
*
|
||||
* @head: the list to test.
|
||||
*/
|
||||
static inline int list_empty_careful(const struct list_head *head)
|
||||
{
|
||||
struct list_head *next = head->next;
|
||||
return (next == head) && (next == head->prev);
|
||||
}
|
||||
|
||||
static inline void __list_splice(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct list_head *first = list->next;
|
||||
struct list_head *last = list->prev;
|
||||
struct list_head *at = head->next;
|
||||
|
||||
first->prev = head;
|
||||
head->next = first;
|
||||
|
||||
last->next = at;
|
||||
at->prev = last;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice - join two lists
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*/
|
||||
static inline void list_splice(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list))
|
||||
__list_splice(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice_init - join two lists and reinitialise the emptied list.
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*
|
||||
* The list at @list is reinitialised
|
||||
*/
|
||||
static inline void list_splice_init(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list)) {
|
||||
__list_splice(list, head);
|
||||
INIT_LIST_HEAD(list);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int list_swap(struct list_head *a, struct list_head *b, struct list_head *list)
|
||||
{
|
||||
if (a->next == list || b->prev == list)
|
||||
return -1;
|
||||
|
||||
list_del(a);
|
||||
list_add(a, b);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* list_entry - get the struct for this entry
|
||||
* @ptr: the &struct list_head pointer.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_entry(ptr, type, member) \
|
||||
container_of(ptr, type, member)
|
||||
|
||||
/**
|
||||
* list_for_each - iterate over a list
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_prev - iterate over a list backwards
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_prev(pos, head) \
|
||||
for (pos = (head)->prev; pos != (head); pos = pos->prev)
|
||||
|
||||
/**
|
||||
* list_for_each_safe - iterate over a list safe against removal of list entry
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @n: another &struct list_head to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_safe(pos, n, head) \
|
||||
for (pos = (head)->next, n = pos->next; pos != (head); pos = n, n = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_entry - iterate over list of given type
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry(pos, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member); &pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_reverse - iterate backwards over list of given type.
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_reverse(pos, head, member) \
|
||||
for (pos = list_entry((head)->prev, typeof(*pos), member); &pos->member != (head); \
|
||||
pos = list_entry(pos->member.prev, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_prepare_entry - prepare a pos entry for use as a start point in
|
||||
* list_for_each_entry_continue
|
||||
* @pos: the type * to use as a start point
|
||||
* @head: the head of the list
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_prepare_entry(pos, head, member) \
|
||||
((pos) ? : list_entry(head, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_continue - iterate over list of given type
|
||||
* continuing after existing point
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_continue(pos, head, member) \
|
||||
for (pos = list_entry(pos->member.next, typeof(*pos), member); &pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_safe(pos, n, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member), \
|
||||
n = list_entry(pos->member.next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.next, typeof(*n), member))
|
||||
|
||||
/**
|
||||
* list_for_each_entry_reverse_safe - iterate over list of given type safe against removal of list entry
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @n: another type * to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry_reverse_safe(pos, n, head, member) \
|
||||
for (pos = list_entry((head)->prev, typeof(*pos), member), \
|
||||
n = list_entry(pos->member.prev, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.prev, typeof(*n), member))
|
||||
|
||||
#endif /* __LIST_H__ */
|
|
@ -1,318 +0,0 @@
|
|||
#include "list.h"
|
||||
#include "slab.h"
|
||||
|
||||
#include "kmem.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
LIST_HEAD(cache_list);
|
||||
struct cache_struct *cachep;
|
||||
struct cache_struct *slabp;
|
||||
|
||||
struct cache_struct *kmem_cache_create(const char *name, intptr_t obj_size, handler_t ctor, handler_t dtor)
|
||||
{
|
||||
struct cache_struct *cp;
|
||||
|
||||
cp = kmem_cache_alloc(cachep);
|
||||
KASSERT(cp);
|
||||
|
||||
strncpy(cp->name, name, CACHE_NAME_BUF_SIZE-1);
|
||||
cp->obj_size = obj_size;
|
||||
cp->page_nr = obj_size * 8 / PG_SIZE + 1;
|
||||
cp->ctor = ctor;
|
||||
cp->dtor = dtor;
|
||||
cp->free_objs = 0;
|
||||
|
||||
if (cp->obj_size < (PG_SIZE >> 3))
|
||||
cp->num = (PG_SIZE - sizeof(struct slab_struct)) / (sizeof(bufctl_t) + cp->obj_size);
|
||||
else
|
||||
cp->num = PG_SIZE / cp->obj_size;
|
||||
|
||||
cp->total_objs = 0;
|
||||
|
||||
INIT_LIST_HEAD(&cp->slab_full);
|
||||
INIT_LIST_HEAD(&cp->slab_partial);
|
||||
INIT_LIST_HEAD(&cp->slab_free);
|
||||
INIT_LIST_HEAD(&cp->next);
|
||||
|
||||
list_add_tail(&cp->next, &cache_list);
|
||||
|
||||
DEBUG(0, 1, "Cache \"%s\" (size:%d) created\n", name, obj_size);
|
||||
|
||||
return cp;
|
||||
}
|
||||
|
||||
static inline bufctl_t *slab_bufctl(struct slab_struct *sp)
|
||||
{
|
||||
return (bufctl_t*)(sp+1);
|
||||
}
|
||||
|
||||
static void cache_init_objs(struct cache_struct *cp, struct slab_struct *sp, unsigned long ctor_flags)
|
||||
{
|
||||
intptr_t i;
|
||||
|
||||
DEBUG(0, 1, " %s:cp->num =%d\n", cp->name, cp->num);
|
||||
|
||||
for (i = 0; i < cp->num; i++) {
|
||||
|
||||
void *objp = (void*)(sp->s_mem + cp->obj_size*i);
|
||||
|
||||
if (cp->ctor)
|
||||
cp->ctor(objp, cp, ctor_flags);
|
||||
|
||||
slab_bufctl(sp)[i] = (bufctl_t)(i+1);
|
||||
}
|
||||
|
||||
slab_bufctl(sp)[i-1] = (bufctl_t)BUFCTL_END;
|
||||
sp->next_free = 0;
|
||||
}
|
||||
|
||||
static void kmem_cache_grow(struct cache_struct *cp)
|
||||
{
|
||||
void *addr;
|
||||
struct slab_struct *sp;
|
||||
struct page_struct *pg_des;
|
||||
int i;
|
||||
|
||||
addr = alloc_pages(cp->page_nr);
|
||||
KASSERT(addr);
|
||||
|
||||
if (cp->obj_size < (PG_SIZE >> 3)) {
|
||||
|
||||
sp = (struct slab_struct*)addr;
|
||||
sp->s_mem = (void*)sp + sizeof(struct slab_struct) + sizeof(bufctl_t)*cp->num;
|
||||
}
|
||||
else {
|
||||
sp = (struct slab_struct*)kmem_cache_alloc(slabp);
|
||||
KASSERT(sp);
|
||||
|
||||
sp->s_mem = addr;
|
||||
}
|
||||
|
||||
pg_des = addr_to_pf_des(addr);
|
||||
|
||||
i = cp->page_nr;
|
||||
while (i--) {
|
||||
|
||||
SET_PAGE_CACHE(pg_des, cp);
|
||||
SET_PAGE_SLAB(pg_des, sp);
|
||||
pg_des++;
|
||||
}
|
||||
|
||||
sp->cache = cp;
|
||||
sp->ref_cnt = 0;
|
||||
|
||||
cache_init_objs(cp, sp, 0);
|
||||
cp->free_objs += cp->num;
|
||||
cp->total_objs += cp->num;
|
||||
|
||||
INIT_LIST_HEAD(&sp->list);
|
||||
list_add_tail(&sp->list, &cp->slab_free);
|
||||
|
||||
DEBUG(0, 1, " %s:grow up, get %d more free object\n", cp->name, cp->free_objs);
|
||||
}
|
||||
|
||||
static void *kmem_slab_refill(struct slab_struct *sp)
|
||||
{
|
||||
void *buf_addr;
|
||||
intptr_t idx;
|
||||
|
||||
idx = sp->next_free;
|
||||
sp->next_free = (intptr_t)(slab_bufctl(sp)[idx]);
|
||||
slab_bufctl(sp)[idx] = BUFCTL_END;
|
||||
|
||||
DEBUG(0, 1, " %s:allocating %uth obj in a slab of Cache \n", sp->cache->name, idx);
|
||||
|
||||
if (sp->next_free == (intptr_t)BUFCTL_END) {
|
||||
|
||||
DEBUG(0, 1, " %s:move from slab_partial to slab_full\n", sp->cache->name);
|
||||
list_move(&sp->list, &sp->cache->slab_full);
|
||||
}
|
||||
else if (sp->ref_cnt == 0) {
|
||||
|
||||
DEBUG(0, 1, " %s:move from slab_free to slab_partial\n", sp->cache->name);
|
||||
list_move(&sp->list, &sp->cache->slab_partial);
|
||||
}
|
||||
|
||||
sp->ref_cnt++;
|
||||
sp->cache->free_objs--;
|
||||
buf_addr = sp->s_mem + idx*sp->cache->obj_size;
|
||||
|
||||
return buf_addr;
|
||||
}
|
||||
|
||||
static void slab_print_list(struct cache_struct *cp)
|
||||
{
|
||||
DEBUG(0, 1, " %s:partial[%c], free[%c], full[%c] %3d/%3d (%3d)\n",
|
||||
cp->name,
|
||||
list_empty(&cp->slab_partial)?' ':'*',
|
||||
list_empty(&cp->slab_free)?' ':'*',
|
||||
list_empty(&cp->slab_full)?' ':'*',
|
||||
cp->free_objs,
|
||||
cp->total_objs,
|
||||
cp->num);
|
||||
}
|
||||
|
||||
void *kmem_cache_alloc(struct cache_struct *cp)
|
||||
{
|
||||
struct slab_struct *sp;
|
||||
|
||||
slab_print_list(cp);
|
||||
DEBUG(0, 1, " %s:free_objs = %d/%d\n", cp->name, cp->free_objs, cp->num);
|
||||
|
||||
while (!cp->free_objs)
|
||||
kmem_cache_grow(cp);
|
||||
|
||||
list_for_each_entry(sp, &cp->slab_partial, list) {
|
||||
|
||||
DEBUG(0, 1, " %s:get a free obj from slab_partial list\n", cp->name);
|
||||
return kmem_slab_refill(sp);
|
||||
}
|
||||
|
||||
list_for_each_entry(sp, &cp->slab_free, list) {
|
||||
|
||||
DEBUG(0, 1, " %s:get a free obj from slab_free list\n", cp->name);
|
||||
return kmem_slab_refill(sp);
|
||||
}
|
||||
|
||||
KPANIC("%s:failed to alloc a free slab\n", cp->name);
|
||||
}
|
||||
|
||||
void kmem_cache_free(struct cache_struct *cp, void *buf_addr)
|
||||
{
|
||||
struct page_struct *pg;
|
||||
struct slab_struct *sp;
|
||||
intptr_t idx;
|
||||
|
||||
pg = addr_to_pf_des(buf_addr);
|
||||
sp = GET_PAGE_SLAB(pg);
|
||||
|
||||
idx = ((intptr_t)(buf_addr - sp->s_mem)) / cp->obj_size;
|
||||
|
||||
slab_bufctl(sp)[idx] = (bufctl_t)sp->next_free;
|
||||
sp->next_free = idx;
|
||||
|
||||
DEBUG(0, 1, " %s:freeing %uth obj in a slab\n", cp->name, idx);
|
||||
|
||||
if (sp->ref_cnt == cp->num) {
|
||||
|
||||
DEBUG(0, 1, " %s:move from slab_full to slab_partial\n", cp->name);
|
||||
list_move(&sp->list, &sp->cache->slab_partial);
|
||||
}
|
||||
else if (sp->ref_cnt == 1) {
|
||||
|
||||
DEBUG(0, 1, " %s:move from slab_partial to slab_free\n", cp->name);
|
||||
list_move(&sp->list, &sp->cache->slab_free);
|
||||
}
|
||||
|
||||
cp->free_objs++;
|
||||
sp->ref_cnt--;
|
||||
}
|
||||
|
||||
void kmem_cache_destory(struct cache_struct *cp)
|
||||
{
|
||||
if (!cp)
|
||||
return;
|
||||
}
|
||||
|
||||
void kmem_cache_reap(struct cache_struct *cp)
|
||||
{
|
||||
struct slab_struct *sp, *tmp;
|
||||
|
||||
slab_print_list(cp);
|
||||
|
||||
list_for_each_entry_safe(sp, tmp, &cp->slab_free, list) {
|
||||
|
||||
list_del(&sp->list);
|
||||
|
||||
if (cp->obj_size < (PG_SIZE >> 3))
|
||||
|
||||
free_pages(sp);
|
||||
else
|
||||
free_pages(sp->s_mem);
|
||||
|
||||
cp->free_objs -= cp->num;
|
||||
|
||||
DEBUG(0, 1, " %s:cache shrink, free_objs = %d\n", cp->name, cp->free_objs);
|
||||
}
|
||||
}
|
||||
|
||||
void init_cache(void)
|
||||
{
|
||||
DEBUG(1, 0, "*************************************************\n");
|
||||
DEBUG(1, 0, "* Initializeing SLAB *\n");
|
||||
DEBUG(1, 0, "*************************************************\n");
|
||||
|
||||
/* Initialize the cachep statically */
|
||||
cachep = (struct cache_struct*)alloc_page();
|
||||
KASSERT(cachep);
|
||||
|
||||
strncpy(cachep->name, "cachep", CACHE_NAME_BUF_SIZE-1);
|
||||
|
||||
cachep->obj_size = sizeof(struct cache_struct);
|
||||
cachep->page_nr = sizeof(struct cache_struct) * 8 / PG_SIZE + 1;
|
||||
cachep->ctor = (void*)0;
|
||||
cachep->dtor = (void*)0;
|
||||
cachep->num = (PG_SIZE - sizeof(struct slab_struct)) / (sizeof(bufctl_t) + cachep->obj_size);
|
||||
cachep->free_objs = 0;
|
||||
cachep->total_objs = 0;
|
||||
|
||||
INIT_LIST_HEAD(&cachep->slab_full);
|
||||
INIT_LIST_HEAD(&cachep->slab_partial);
|
||||
INIT_LIST_HEAD(&cachep->slab_free);
|
||||
INIT_LIST_HEAD(&cachep->next);
|
||||
|
||||
list_add_tail(&cachep->next, &cache_list);
|
||||
|
||||
slabp = kmem_cache_create("slabp", sizeof(struct cache_struct), (void*)0, (void*)0);
|
||||
|
||||
#ifdef CONFIG_KMEM_USING_SLAB
|
||||
init_general_caches();
|
||||
#endif
|
||||
}
|
||||
|
||||
#define TBL_SIZE 10
|
||||
#define MIN_OBJ_SIZE 8
|
||||
|
||||
struct cache_tbl_entry {
|
||||
|
||||
struct cache_struct *cp;
|
||||
intptr_t size;
|
||||
};
|
||||
|
||||
struct cache_tbl_entry cache_tbl[TBL_SIZE];
|
||||
|
||||
void init_general_caches(void)
|
||||
{
|
||||
char name_buf[CACHE_NAME_BUF_SIZE];
|
||||
intptr_t size;
|
||||
intptr_t i;
|
||||
|
||||
size = MIN_OBJ_SIZE;
|
||||
|
||||
DEBUG(1, 0, "*************************************************\n");
|
||||
DEBUG(1, 0, "* Initializeing SLAB(General Object Caches) *\n");
|
||||
DEBUG(1, 0, "*************************************************\n");
|
||||
|
||||
for (i = 0; i < TBL_SIZE; i++) {
|
||||
|
||||
sprintf(name_buf, "gen_cache_%d", size);
|
||||
cache_tbl[i].cp = kmem_cache_create(name_buf, size, (void*)0, (void*)0);
|
||||
cache_tbl[i].size = size;
|
||||
size *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
void *kmem_cache_alloc_gen(intptr_t size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < TBL_SIZE; i++) {
|
||||
|
||||
if (cache_tbl[i].size > size)
|
||||
return kmem_cache_alloc(cache_tbl[i].cp);
|
||||
}
|
||||
|
||||
return (void*)0;
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
#ifndef __SLAB_H__
|
||||
#define __SLAB_H__
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "list.h"
|
||||
|
||||
#define BUFCTL_END (((bufctl_t)(~0U))-0)
|
||||
#define BUFCTL_FREE (((bufctl_t)(~0U))-1)
|
||||
#define SLAB_LIMIT (((bufctl_t)(~0U))-2)
|
||||
|
||||
#define CACHE_NAME_BUF_SIZE 20
|
||||
|
||||
struct cache_struct;
|
||||
|
||||
typedef void (*handler_t)(void *, struct cache_struct*, intptr_t);
|
||||
|
||||
struct cache_struct {
|
||||
|
||||
struct list_head slab_full;
|
||||
struct list_head slab_partial;
|
||||
struct list_head slab_free;
|
||||
struct list_head next;
|
||||
char name[CACHE_NAME_BUF_SIZE];
|
||||
intptr_t obj_size;
|
||||
intptr_t page_nr;
|
||||
intptr_t num;
|
||||
intptr_t free_objs;
|
||||
intptr_t total_objs;
|
||||
handler_t ctor;
|
||||
handler_t dtor;
|
||||
};
|
||||
|
||||
struct slab_struct {
|
||||
|
||||
struct cache_struct *cache;
|
||||
struct list_head list;
|
||||
|
||||
void *s_mem;
|
||||
int ref_cnt;
|
||||
intptr_t next_free;
|
||||
};
|
||||
|
||||
typedef intptr_t *bufctl_t;
|
||||
|
||||
extern struct cache_struct *kmem_cache_create(const char *name, intptr_t obj_size, handler_t ctor, handler_t dtor);
|
||||
extern void *kmem_cache_alloc(struct cache_struct *cp);
|
||||
extern void kmem_cache_free(struct cache_struct *cp, void *buf_addr);
|
||||
extern void *kmem_cache_alloc_gen(intptr_t size);
|
||||
extern void kmem_cache_destory(struct cache_struct *cp);
|
||||
extern void kmem_cache_reap(struct cache_struct *cp);
|
||||
extern void init_cache(void);
|
||||
extern void init_general_caches(void);
|
||||
|
||||
#define SET_PAGE_CACHE(pg,x) ((pg)->lru.next = (struct list_head*)(x))
|
||||
#define GET_PAGE_CACHE(pg) ((struct cache_struct*)(pg)->lru.next)
|
||||
#define SET_PAGE_SLAB(pg,x) ((pg)->lru.prev = (struct list_head*)(x))
|
||||
#define GET_PAGE_SLAB(pg) ((struct slab_struct*)(pg)->lru.prev)
|
||||
|
||||
#endif /* __SLAB_H__ */
|
|
@ -1,6 +0,0 @@
|
|||
lib-y += do_printf.o
|
||||
lib-y += fgets.o
|
||||
lib-y += file.o
|
||||
lib-y += fprintf.o
|
||||
lib-y += fputs.o
|
||||
lib-y += printf.o
|
|
@ -1,280 +0,0 @@
|
|||
#include <string.h> /* strlen() */
|
||||
#include "do_printf.h"
|
||||
|
||||
/*****************************************************************************
|
||||
Revised Jan 28, 2002
|
||||
- changes to make characters 0x80-0xFF display properly
|
||||
|
||||
Revised June 10, 2001
|
||||
- changes to make vsprintf() terminate string with '\0'
|
||||
|
||||
Revised May 12, 2000
|
||||
- math in DO_NUM is now unsigned, as it should be
|
||||
- %0 flag (pad left with zeroes) now works
|
||||
- actually did some TESTING, maybe fixed some other bugs
|
||||
|
||||
name: do_printf
|
||||
action: minimal subfunction for ?printf, calls function
|
||||
'fn' with arg 'ptr' for each character to be output
|
||||
returns:total number of characters output
|
||||
|
||||
%[flag][width][.prec][mod][conv]
|
||||
flag: - left justify, pad right w/ blanks DONE
|
||||
0 pad left w/ 0 for numerics DONE
|
||||
+ always print sign, + or - no
|
||||
' ' (blank) no
|
||||
# (???) no
|
||||
|
||||
width: (field width) DONE
|
||||
|
||||
prec: (precision) no
|
||||
|
||||
conv: d,i decimal int DONE
|
||||
u decimal unsigned DONE
|
||||
o octal DONE
|
||||
x,X hex DONE
|
||||
f,e,g,E,G float no
|
||||
c char DONE
|
||||
s string DONE
|
||||
p ptr DONE
|
||||
|
||||
mod: N near ptr DONE
|
||||
F far ptr no
|
||||
h short (16-bit) int DONE
|
||||
l long (32-bit) int DONE
|
||||
L long long (64-bit) int no
|
||||
*****************************************************************************/
|
||||
|
||||
/* flags used in processing format string */
|
||||
#define PR_LJ 0x01 /* left justify */
|
||||
#define PR_CA 0x02 /* use A-F instead of a-f for hex */
|
||||
#define PR_SG 0x04 /* signed numeric conversion (%d vs. %u) */
|
||||
#define PR_32 0x08 /* long (32-bit) numeric conversion */
|
||||
#define PR_16 0x10 /* short (16-bit) numeric conversion */
|
||||
#define PR_WS 0x20 /* PR_SG set and num was < 0 */
|
||||
#define PR_LZ 0x40 /* pad left with '0' instead of ' ' */
|
||||
#define PR_FP 0x80 /* pointers are far */
|
||||
|
||||
/* largest number handled is 2^32-1, lowest radix handled is 8.
|
||||
2^32-1 in base 8 has 11 digits (add 5 for trailing NUL and for slop) */
|
||||
#define PR_BUFLEN 16
|
||||
|
||||
int do_printf(const char *fmt, va_list args, fnptr_t fn, void *ptr)
|
||||
{
|
||||
unsigned state, flags, radix, actual_wd, count, given_wd;
|
||||
unsigned char *where, buf[PR_BUFLEN];
|
||||
long num;
|
||||
|
||||
state = flags = count = given_wd = 0;
|
||||
/* begin scanning format specifier list */
|
||||
for(; *fmt; fmt++)
|
||||
{
|
||||
switch(state)
|
||||
{
|
||||
/* STATE 0: AWAITING % */
|
||||
case 0:
|
||||
if(*fmt != '%') /* not %... */
|
||||
{
|
||||
fn(*fmt, &ptr); /* ...just echo it */
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
/* found %, get next char and advance state to check if next char is a flag */
|
||||
state++;
|
||||
fmt++;
|
||||
/* FALL THROUGH */
|
||||
/* STATE 1: AWAITING FLAGS (%-0) */
|
||||
case 1:
|
||||
if(*fmt == '%') /* %% */
|
||||
{
|
||||
fn(*fmt, &ptr);
|
||||
count++;
|
||||
state = flags = given_wd = 0;
|
||||
break;
|
||||
}
|
||||
if(*fmt == '-')
|
||||
{
|
||||
if(flags & PR_LJ)/* %-- is illegal */
|
||||
state = flags = given_wd = 0;
|
||||
else
|
||||
flags |= PR_LJ;
|
||||
break;
|
||||
}
|
||||
/* not a flag char: advance state to check if it's field width */
|
||||
state++;
|
||||
/* check now for '%0...' */
|
||||
if(*fmt == '0')
|
||||
{
|
||||
flags |= PR_LZ;
|
||||
fmt++;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
/* STATE 2: AWAITING (NUMERIC) FIELD WIDTH */
|
||||
case 2:
|
||||
if(*fmt >= '0' && *fmt <= '9')
|
||||
{
|
||||
given_wd = 10 * given_wd +
|
||||
(*fmt - '0');
|
||||
break;
|
||||
}
|
||||
/* not field width: advance state to check if it's a modifier */
|
||||
state++;
|
||||
/* FALL THROUGH */
|
||||
/* STATE 3: AWAITING MODIFIER CHARS (FNlh) */
|
||||
case 3:
|
||||
if(*fmt == 'F')
|
||||
{
|
||||
flags |= PR_FP;
|
||||
break;
|
||||
}
|
||||
if(*fmt == 'N')
|
||||
break;
|
||||
if(*fmt == 'l')
|
||||
{
|
||||
flags |= PR_32;
|
||||
break;
|
||||
}
|
||||
if(*fmt == 'h')
|
||||
{
|
||||
flags |= PR_16;
|
||||
break;
|
||||
}
|
||||
/* not modifier: advance state to check if it's a conversion char */
|
||||
state++;
|
||||
/* FALL THROUGH */
|
||||
/* STATE 4: AWAITING CONVERSION CHARS (Xxpndiuocs) */
|
||||
case 4:
|
||||
where = buf + PR_BUFLEN - 1;
|
||||
*where = '\0';
|
||||
switch(*fmt)
|
||||
{
|
||||
case 'X':
|
||||
flags |= PR_CA;
|
||||
/* FALL THROUGH */
|
||||
/* xxx - far pointers (%Fp, %Fn) not yet supported */
|
||||
case 'x':
|
||||
case 'p':
|
||||
case 'n':
|
||||
radix = 16;
|
||||
goto DO_NUM;
|
||||
case 'd':
|
||||
case 'i':
|
||||
flags |= PR_SG;
|
||||
/* FALL THROUGH */
|
||||
case 'u':
|
||||
radix = 10;
|
||||
goto DO_NUM;
|
||||
case 'o':
|
||||
radix = 8;
|
||||
/* load the value to be printed. l=long=32 bits: */
|
||||
DO_NUM: if(flags & PR_32)
|
||||
num = va_arg(args, unsigned long);
|
||||
/* h=short=16 bits (signed or unsigned) */
|
||||
else if(flags & PR_16)
|
||||
{
|
||||
if(flags & PR_SG)
|
||||
num = va_arg(args, unsigned long);
|
||||
else
|
||||
num = va_arg(args, unsigned long);
|
||||
}
|
||||
/* no h nor l: sizeof(int) bits (signed or unsigned) */
|
||||
else
|
||||
{
|
||||
if(flags & PR_SG)
|
||||
num = va_arg(args, unsigned long);
|
||||
else
|
||||
num = va_arg(args, unsigned long);
|
||||
}
|
||||
/* take care of sign */
|
||||
if(flags & PR_SG)
|
||||
{
|
||||
if(num < 0)
|
||||
{
|
||||
flags |= PR_WS;
|
||||
num = -num;
|
||||
}
|
||||
}
|
||||
/* convert binary to octal/decimal/hex ASCII
|
||||
OK, I found my mistake. The math here is _always_ unsigned */
|
||||
do
|
||||
{
|
||||
unsigned long temp;
|
||||
|
||||
temp = (unsigned long)num % radix;
|
||||
where--;
|
||||
if(temp < 10)
|
||||
*where = temp + '0';
|
||||
else if(flags & PR_CA)
|
||||
*where = temp - 10 + 'A';
|
||||
else
|
||||
*where = temp - 10 + 'a';
|
||||
num = (unsigned long)num / radix;
|
||||
}
|
||||
while(num != 0);
|
||||
goto EMIT;
|
||||
case 'c':
|
||||
/* disallow pad-left-with-zeroes for %c */
|
||||
flags &= ~PR_LZ;
|
||||
where--;
|
||||
*where = (unsigned char)va_arg(args,
|
||||
unsigned int);
|
||||
actual_wd = 1;
|
||||
goto EMIT2;
|
||||
case 's':
|
||||
/* disallow pad-left-with-zeroes for %s */
|
||||
flags &= ~PR_LZ;
|
||||
where = (unsigned char *)va_arg(args, unsigned int);
|
||||
EMIT:
|
||||
actual_wd = strlen((const char *)where);
|
||||
if(flags & PR_WS)
|
||||
actual_wd++;
|
||||
/* if we pad left with ZEROES, do the sign now */
|
||||
if((flags & (PR_WS | PR_LZ)) ==
|
||||
(PR_WS | PR_LZ))
|
||||
{
|
||||
fn('-', &ptr);
|
||||
count++;
|
||||
}
|
||||
/* pad on left with spaces or zeroes (for right justify) */
|
||||
EMIT2: if((flags & PR_LJ) == 0)
|
||||
{
|
||||
while(given_wd > actual_wd)
|
||||
{
|
||||
fn(flags & PR_LZ ? '0' :
|
||||
' ', &ptr);
|
||||
count++;
|
||||
given_wd--;
|
||||
}
|
||||
}
|
||||
/* if we pad left with SPACES, do the sign now */
|
||||
if((flags & (PR_WS | PR_LZ)) == PR_WS)
|
||||
{
|
||||
fn('-', &ptr);
|
||||
count++;
|
||||
}
|
||||
/* emit string/char/converted number */
|
||||
while(*where != '\0')
|
||||
{
|
||||
fn(*where++, &ptr);
|
||||
count++;
|
||||
}
|
||||
/* pad on right with spaces (for left justify) */
|
||||
if(given_wd < actual_wd)
|
||||
given_wd = 0;
|
||||
else given_wd -= actual_wd;
|
||||
for(; given_wd; given_wd--)
|
||||
{
|
||||
fn(' ', &ptr);
|
||||
count++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
state = flags = given_wd = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
#ifndef __DO_PRINTF_H__
|
||||
#define __DO_PRINTF_H__
|
||||
|
||||
#include <stdarg.h> /* va_list, va_arg() */
|
||||
typedef int (*fnptr_t)(unsigned c, void **helper);
|
||||
int do_printf(const char *fmt, va_list args, fnptr_t fn, void *ptr);
|
||||
|
||||
#endif /* __DO_PRINTF_H__ */
|
|
@ -1,73 +0,0 @@
|
|||
#include "uart/uart.h"
|
||||
#include "rtdef.h"
|
||||
#include "rtthread.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
__attribute__((used))
|
||||
int fgetc(FILE *stream)
|
||||
{
|
||||
int c;
|
||||
|
||||
while (!drv_uart_is_kbd_hit()) {
|
||||
rt_thread_delay(1);
|
||||
}
|
||||
|
||||
c = drv_uart_get_char();
|
||||
|
||||
if (c == '\r')
|
||||
c = '\n';
|
||||
|
||||
fputc(c, stream);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
char *fgets(char *s, int size, FILE *stream)
|
||||
{
|
||||
char *p = s;
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < size - 1; i++){
|
||||
|
||||
int c = fgetc(stream);
|
||||
|
||||
if(c == '\n'){
|
||||
|
||||
*p++ = '\n';
|
||||
break;
|
||||
}
|
||||
else if(c == '\0'){
|
||||
|
||||
break;
|
||||
}
|
||||
else if(c < 0){
|
||||
|
||||
return (void*)0;
|
||||
}
|
||||
else{
|
||||
*p++ = c;
|
||||
}
|
||||
}
|
||||
|
||||
*p = '\0';
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int getc(FILE *stream)
|
||||
{
|
||||
return fgetc(stream);
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int getchar(void)
|
||||
{
|
||||
return fgetc((void*)0);
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int ungetc(int c, FILE *stream);
|
|
@ -1,520 +0,0 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "ndsvfs.h"
|
||||
#include "dirent.h"
|
||||
|
||||
__attribute__((used))
|
||||
FILE *fopen(const char *path_name, const char *mode)
|
||||
{
|
||||
NDSVFS_DENTRY *vde = HAL_NULL;
|
||||
NDSVFS_FILE *file = HAL_NULL;
|
||||
UINT32 mode_len;
|
||||
UINT32 fmode = 0;
|
||||
UINT32 i;
|
||||
|
||||
if (HAL_SUCCESS != _ndsvfs_lock())
|
||||
return HAL_NULL;
|
||||
|
||||
// alloc file object
|
||||
file = _ndsvfs_alloc_file();
|
||||
if (file == HAL_NULL)
|
||||
goto _safe_exit;
|
||||
|
||||
// open flags
|
||||
if (mode == HAL_NULL)
|
||||
mode_len = 0;
|
||||
else
|
||||
mode_len = (UINT32)strlen(mode);
|
||||
|
||||
for (i = 0; i < mode_len; ++i)
|
||||
{
|
||||
switch (mode[i])
|
||||
{
|
||||
case 'r':
|
||||
fmode |= NDSVFS_FOPEN_READ;
|
||||
break;
|
||||
case 'w':
|
||||
fmode |= NDSVFS_FOPEN_WRITE;
|
||||
break;
|
||||
case 'a':
|
||||
fmode |= NDSVFS_FOPEN_APPEND;
|
||||
break;
|
||||
case '+':
|
||||
fmode |= NDSVFS_FOPEN_PLUS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fmode == 0)
|
||||
goto _safe_exit;
|
||||
#if 0
|
||||
// (todo) current imp should be read only
|
||||
if (fmode & ~NDSVFS_FOPEN_READ)
|
||||
goto _safe_exit;
|
||||
if (!(fmode & NDSVFS_FOPEN_READ))
|
||||
goto _safe_exit;
|
||||
// ~(todo)
|
||||
#endif
|
||||
// lookup file entry
|
||||
if (path_name == HAL_NULL)
|
||||
goto _safe_exit;
|
||||
|
||||
if ((INT)strlen(path_name) == 0)
|
||||
goto _safe_exit;
|
||||
|
||||
vde = _ndsvfs_path_lookup((const char *)path_name);
|
||||
if (!vde)
|
||||
{
|
||||
// (todo) create the file if not exist and flag is not read only
|
||||
goto _safe_exit;
|
||||
}
|
||||
|
||||
// current imp allows only regular file
|
||||
// we can open dir now, so I comments the codes
|
||||
#if 0
|
||||
if (vde->inode->mode & NDSVFS_INM_ATTR_MASK)
|
||||
goto _safe_exit;
|
||||
#endif
|
||||
// notify file system to open the file
|
||||
// (todo) call this only when user mode reference to the file is 0.
|
||||
if (HAL_SUCCESS != vde->sb->open_file(vde, fmode))
|
||||
goto _safe_exit;
|
||||
|
||||
file->flags = fmode;
|
||||
file->vde = vde;
|
||||
//file->pos = 0;
|
||||
|
||||
//DEBUG(0, 1,"fopen() 0x%08lx\r\n", (UINT32)file);
|
||||
|
||||
_ndsvfs_unlock();
|
||||
|
||||
// todo
|
||||
return (FILE *)file;
|
||||
|
||||
_safe_exit:
|
||||
|
||||
if (vde)
|
||||
NDSVFS_DEREF(vde);
|
||||
file->vde = HAL_NULL;
|
||||
|
||||
if (file)
|
||||
NDSVFS_DEREF(file);
|
||||
|
||||
_ndsvfs_unlock();
|
||||
|
||||
return HAL_NULL;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int fclose(FILE *stream)
|
||||
{
|
||||
if (stream == HAL_NULL)
|
||||
return (int)-NDS_VFSD_INVALID_PARAMETER;
|
||||
|
||||
if (HAL_SUCCESS != _ndsvfs_lock())
|
||||
return (int)HAL_ERR_INVALID_OPERATION;
|
||||
|
||||
//DEBUG(0, 1,"fclose() 0x%08lx\r\n", (UINT32)stream);
|
||||
|
||||
// (todo) flush the file contents if ever been modified
|
||||
|
||||
// notify file system to close the file
|
||||
// (todo) call this only when user mode reference to the file decreased to 0.
|
||||
((NDSVFS_FILE *)stream)->vde->sb->close_file(((NDSVFS_FILE *)stream)->vde);
|
||||
|
||||
// release file references
|
||||
if (stream)
|
||||
NDSVFS_DEREF(stream);
|
||||
|
||||
if (HAL_SUCCESS != _ndsvfs_unlock())
|
||||
return (int)HAL_ERR_INVALID_OPERATION;
|
||||
|
||||
return (int)HAL_SUCCESS;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
size_t fread(void *ptr, size_t size, size_t count, FILE *stream)
|
||||
{
|
||||
STATUS status;
|
||||
UINT32 d_size = (UINT32)size * (UINT32)count;
|
||||
UINT32 r_size; // size actually been read
|
||||
|
||||
#if 1
|
||||
DEBUG(0, 1,"fread() 0x%08lx ptr(0x%08lx) size(0x%08lx) count(0x%08lx)\r\n",
|
||||
(UINT32)stream, (UINT32)ptr, (UINT32)size, (UINT32)count);
|
||||
#endif
|
||||
|
||||
if (stream == HAL_NULL)
|
||||
{
|
||||
((NDSVFS_FILE *)stream)->err = NDS_VFSD_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (HAL_SUCCESS != _ndsvfs_lock())
|
||||
{
|
||||
((NDSVFS_FILE *)stream)->err = HAL_ERR_INVALID_OPERATION;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEBUG(0, 1,"fread() 0x%08lx >>\r\n", (UINT32)stream);
|
||||
|
||||
if (((NDSVFS_FILE *)stream)->pos < 0)
|
||||
{
|
||||
DEBUG(0, 1,"fread() 0x%08lx <<\r\n", (UINT32)stream);
|
||||
_ndsvfs_unlock();
|
||||
((NDSVFS_FILE *)stream)->err = HAL_ERR_INVALID_START;
|
||||
return 0;
|
||||
}
|
||||
|
||||
status = ((NDSVFS_FILE *)stream)->vde->sb->read_file(((NDSVFS_FILE *)stream)->vde,
|
||||
ptr, (UINT32)((NDSVFS_FILE *)stream)->pos, d_size, &r_size);
|
||||
|
||||
if (status == NDS_VFSD_END_OF_FILE)
|
||||
{
|
||||
((NDSVFS_FILE *)stream)->eof = HAL_TRUE;
|
||||
status = HAL_SUCCESS;
|
||||
}
|
||||
|
||||
if (status == HAL_SUCCESS)
|
||||
((NDSVFS_FILE *)stream)->pos += (INT32)r_size;
|
||||
else
|
||||
r_size = 0;
|
||||
|
||||
DEBUG(0, 1,"fread() 0x%08lx <<\r\n", (UINT32)stream);
|
||||
if (HAL_SUCCESS != _ndsvfs_unlock())
|
||||
{
|
||||
((NDSVFS_FILE *)stream)->err = HAL_ERR_INVALID_OPERATION;
|
||||
DEBUG(0, 1,"fread() 0x%08lx << unlock fail\r\n", (UINT32)stream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int)((size_t)r_size / size);
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream)
|
||||
{
|
||||
STATUS status;
|
||||
UINT32 d_size = (UINT32)size * (UINT32)count;
|
||||
UINT32 w_size; // size actually been write
|
||||
|
||||
#if 1
|
||||
DEBUG(0, 1,"fwrite() 0x%08lx ptr(0x%08lx) size(0x%08lx) count(0x%08lx)\r\n",
|
||||
(UINT32)stream, (UINT32)ptr, (UINT32)size, (UINT32)count);
|
||||
#endif
|
||||
|
||||
if (stream == HAL_NULL)
|
||||
{
|
||||
((NDSVFS_FILE *)stream)->err = NDS_VFSD_INVALID_PARAMETER;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (HAL_SUCCESS != _ndsvfs_lock())
|
||||
{
|
||||
((NDSVFS_FILE *)stream)->err = HAL_ERR_INVALID_OPERATION;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEBUG(0, 1,"fwrite() 0x%08lx >>\r\n", (UINT32)stream);
|
||||
|
||||
if (((NDSVFS_FILE *)stream)->pos < 0)
|
||||
{
|
||||
DEBUG(0, 1,"fwrite() 0x%08lx <<\r\n", (UINT32)stream);
|
||||
_ndsvfs_unlock();
|
||||
((NDSVFS_FILE *)stream)->err = HAL_ERR_INVALID_START;
|
||||
return 0;
|
||||
}
|
||||
|
||||
status = ((NDSVFS_FILE *)stream)->vde->sb->write_file(((NDSVFS_FILE *)stream)->vde,
|
||||
ptr, (UINT32)((NDSVFS_FILE *)stream)->pos, d_size, &w_size);
|
||||
|
||||
if (status == NDS_VFSD_END_OF_FILE)
|
||||
{
|
||||
((NDSVFS_FILE *)stream)->eof = HAL_TRUE;
|
||||
status = HAL_SUCCESS;
|
||||
}
|
||||
|
||||
if (status == HAL_SUCCESS)
|
||||
((NDSVFS_FILE *)stream)->pos += (INT32)w_size;
|
||||
else
|
||||
w_size = 0;
|
||||
|
||||
DEBUG(0, 1,"fwrite() 0x%08lx <<\r\n", (UINT32)stream);
|
||||
if (HAL_SUCCESS != _ndsvfs_unlock())
|
||||
{
|
||||
((NDSVFS_FILE *)stream)->err = HAL_ERR_INVALID_OPERATION;
|
||||
DEBUG(0, 1,"fwrite() 0x%08lx << unlock fail\r\n", (UINT32)stream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int)((size_t)w_size / size);
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int fflush(FILE *stream)
|
||||
{
|
||||
if (stream == HAL_NULL)
|
||||
return (int)NDS_VFSD_INVALID_PARAMETER;
|
||||
|
||||
// todo
|
||||
return (int)HAL_SUCCESS;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int fseek(FILE *stream, int offset, int origin)
|
||||
{
|
||||
INT32 pos;
|
||||
|
||||
if (stream == HAL_NULL)
|
||||
return (int)NDS_VFSD_INVALID_PARAMETER;
|
||||
|
||||
if (HAL_SUCCESS != _ndsvfs_lock())
|
||||
return (int)HAL_ERR_INVALID_OPERATION;
|
||||
|
||||
pos = ((NDSVFS_FILE *)stream)->pos;
|
||||
|
||||
//DEBUG(0, 1,"fseek() 0x%08lx >>\r\n", (UINT32)stream);
|
||||
//DEBUG(0, 1,"pos (cur) : 0x%08lx\r\n", pos);
|
||||
//DEBUG(0, 1,"offset : 0x%08lx\r\n", offset);
|
||||
|
||||
switch (origin)
|
||||
{
|
||||
case FSEEK_CUR:
|
||||
pos += offset;
|
||||
break;
|
||||
case FSEEK_END:
|
||||
pos = (INT32)((NDSVFS_FILE *)stream)->vde->inode->size + offset;
|
||||
break;
|
||||
case FSEEK_SET:
|
||||
pos = offset;
|
||||
break;
|
||||
default:
|
||||
//DEBUG(0, 1,"fseek() 0x%08lx <<\r\n", (UINT32)stream);
|
||||
_ndsvfs_unlock();
|
||||
return (int)NDS_VFSD_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//DEBUG(0, 1,"pos (new) : 0x%08lx\r\n", pos);
|
||||
|
||||
/*
|
||||
if (pos > ((NDSVFS_FILE *)stream)->vde->inode->size)
|
||||
{
|
||||
_ndsvfs_unlock();
|
||||
return (int)NDS_VFSD_INVALID_PARAMETER; // todo: might be a valid condition for write-mode
|
||||
}*/
|
||||
|
||||
((NDSVFS_FILE *)stream)->pos = pos;
|
||||
|
||||
//DEBUG(0, 1,"fseek() 0x%08lx <<\r\n", (UINT32)stream);
|
||||
|
||||
if (HAL_SUCCESS != _ndsvfs_unlock())
|
||||
return (int)HAL_ERR_INVALID_OPERATION;
|
||||
|
||||
return (int)HAL_SUCCESS;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
long ftell(FILE *stream)
|
||||
{
|
||||
long pos;
|
||||
|
||||
if (stream == HAL_NULL)
|
||||
return (int)HAL_ERR_INVALID_OPERATION;
|
||||
|
||||
if (HAL_SUCCESS != _ndsvfs_lock())
|
||||
return (int)HAL_ERR_INVALID_OPERATION;
|
||||
|
||||
pos = (long)((NDSVFS_FILE *)stream)->pos;
|
||||
|
||||
if (HAL_SUCCESS != _ndsvfs_unlock())
|
||||
return (int)HAL_ERR_INVALID_OPERATION;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
void frewind(FILE *stream)
|
||||
{
|
||||
if (stream == HAL_NULL)
|
||||
return;
|
||||
|
||||
if (HAL_SUCCESS != _ndsvfs_lock())
|
||||
return;
|
||||
|
||||
((NDSVFS_FILE *)stream)->pos = 0;
|
||||
((NDSVFS_FILE *)stream)->err = 0;
|
||||
((NDSVFS_FILE *)stream)->eof = 0;
|
||||
|
||||
if (HAL_SUCCESS != _ndsvfs_unlock())
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int fgetpos(FILE *stream, fpos_t *position)
|
||||
{
|
||||
if (stream == HAL_NULL)
|
||||
return (int)NDS_VFSD_INVALID_PARAMETER;
|
||||
|
||||
if (position == HAL_NULL)
|
||||
return (int)NDS_VFSD_INVALID_PARAMETER;
|
||||
|
||||
if (HAL_SUCCESS != _ndsvfs_lock())
|
||||
return (int)HAL_ERR_INVALID_OPERATION;
|
||||
|
||||
*position = ((NDSVFS_FILE *)stream)->pos;
|
||||
|
||||
if (HAL_SUCCESS != _ndsvfs_unlock())
|
||||
return (int)HAL_ERR_INVALID_OPERATION;
|
||||
|
||||
return (int)HAL_SUCCESS;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int fsetpos(FILE *stream, const fpos_t *position)
|
||||
{
|
||||
if (stream == HAL_NULL)
|
||||
return (int)NDS_VFSD_INVALID_PARAMETER;
|
||||
|
||||
if (position == HAL_NULL)
|
||||
return (int)NDS_VFSD_INVALID_PARAMETER;
|
||||
|
||||
if (HAL_SUCCESS != _ndsvfs_lock())
|
||||
return (int)HAL_ERR_INVALID_OPERATION;
|
||||
|
||||
if (*position > (INT32)((NDSVFS_FILE *)stream)->vde->inode->size)
|
||||
{
|
||||
_ndsvfs_unlock();
|
||||
return (int)NDS_VFSD_INVALID_PARAMETER; // todo: might be a valid condition for write-mode
|
||||
}
|
||||
|
||||
((NDSVFS_FILE *)stream)->pos = *position;
|
||||
((NDSVFS_FILE *)stream)->eof = 0; // ?? todo: signal eof if position reaches end of file?
|
||||
|
||||
if (HAL_SUCCESS != _ndsvfs_unlock())
|
||||
return (int)HAL_ERR_INVALID_OPERATION;
|
||||
|
||||
return (int)HAL_SUCCESS;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int feof(FILE *stream)
|
||||
{
|
||||
UINT32 eof;
|
||||
|
||||
if (HAL_SUCCESS != _ndsvfs_lock())
|
||||
return (int)HAL_ERR_INVALID_OPERATION;
|
||||
|
||||
eof = ((NDSVFS_FILE *)stream)->eof > 0 ? HAL_TRUE : HAL_FALSE;
|
||||
|
||||
if (HAL_SUCCESS != _ndsvfs_unlock())
|
||||
return (int)HAL_ERR_INVALID_OPERATION;
|
||||
|
||||
return eof;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int ferror(FILE *stream)
|
||||
{
|
||||
UINT32 err;
|
||||
|
||||
if (HAL_SUCCESS != _ndsvfs_lock())
|
||||
return (int)HAL_ERR_INVALID_OPERATION;
|
||||
|
||||
err = ((NDSVFS_FILE *)stream)->err > 0 ? 1 : 0;
|
||||
|
||||
if (HAL_SUCCESS != _ndsvfs_unlock())
|
||||
return (int)HAL_ERR_INVALID_OPERATION;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void fclearerr(FILE *stream)
|
||||
{
|
||||
if (HAL_SUCCESS != _ndsvfs_lock())
|
||||
return;
|
||||
|
||||
((NDSVFS_FILE *)stream)->err = 0;
|
||||
((NDSVFS_FILE *)stream)->eof = 0;
|
||||
|
||||
if (HAL_SUCCESS != _ndsvfs_unlock())
|
||||
return;
|
||||
}
|
||||
extern STATUS _ndsvfs_read_dirs(NDSVFS_DENTRY *vde_parent, NDSVFS_DENTRY **vde_list);
|
||||
__attribute__((used))
|
||||
struct dir *opendir(const char *path)
|
||||
{
|
||||
NDSVFS_FILE *file = NULL;
|
||||
struct dir *dirp = NULL;
|
||||
int status;
|
||||
|
||||
file = (NDSVFS_FILE *)fopen(path, "rb");
|
||||
if (file == NULL) {
|
||||
// ERROR("fopen path=%s\n",path);
|
||||
return (void*)0;
|
||||
}
|
||||
if (!S_ISDIR(file->vde->inode)){
|
||||
fclose((FILE *)file);
|
||||
// ERROR("Not a dir path=%s\n",path);
|
||||
return (void*)0;
|
||||
}
|
||||
|
||||
if (!file->dirp){
|
||||
|
||||
file->dirp = malloc(sizeof(struct dir));
|
||||
KASSERT(file->dirp);
|
||||
dirp = (struct dir*)file->dirp;
|
||||
dirp->d_dirent = malloc(sizeof(struct dirent));
|
||||
KASSERT(dirp->d_dirent);
|
||||
dirp->d_file = file;
|
||||
dirp->d_off = 0;
|
||||
}
|
||||
|
||||
status = _ndsvfs_read_dirs(file->vde, &(dirp->vde_list));
|
||||
dirp->vde_head = dirp->vde_list;
|
||||
dirp->vde_list = NULL;
|
||||
if(status == HAL_FAILURE)
|
||||
return HAL_NULL;
|
||||
return dirp;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int closedir(struct dir *dirp)
|
||||
{
|
||||
NDSVFS_FILE *file = dirp->d_file;
|
||||
|
||||
if (dirp == NULL)
|
||||
return -1;
|
||||
if (file == NULL)
|
||||
return -1;
|
||||
if (dirp->d_dirent != NULL)
|
||||
free(dirp->d_dirent);
|
||||
free(dirp);
|
||||
return fclose((FILE *)file);
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
struct dirent *readdir(struct dir *dirp)
|
||||
{
|
||||
/* this is the first time, becasue the vde_list is pointed to null */
|
||||
if (dirp->vde_list == NULL && dirp->vde_head != NULL) {
|
||||
strcpy(dirp->d_dirent->d_name, dirp->vde_head->name.utf_name);
|
||||
dirp->vde_list = NDS_LIST_ENTITY(dirp->vde_head->c_chain.next, NDSVFS_DENTRY, c_chain);
|
||||
return dirp->d_dirent;
|
||||
}
|
||||
/* this is not the first time. */
|
||||
else if (dirp->vde_list != dirp->vde_head) {
|
||||
strcpy(dirp->d_dirent->d_name, dirp->vde_list->name.utf_name);
|
||||
dirp->vde_list = NDS_LIST_ENTITY(dirp->vde_list->c_chain.next, NDSVFS_DENTRY, c_chain);
|
||||
return dirp->d_dirent;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int fstat(FILE* fd, struct stat *buf)
|
||||
{
|
||||
NDSVFS_FILE *file = (NDSVFS_FILE *)fd;
|
||||
if (file == HAL_NULL)
|
||||
return -1;
|
||||
return file->vde->sb->stat_file(file->vde, buf);
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
#include <stdio.h>
|
||||
|
||||
__attribute__((used))
|
||||
int fprintf(FILE *stream, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int ret_val;
|
||||
|
||||
va_start(args, fmt);
|
||||
ret_val = vprintf(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return ret_val;
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
#include "uart/uart.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
__attribute__((used))
|
||||
int fputc(int c, FILE *stream)
|
||||
{
|
||||
if (c == '\n')
|
||||
drv_uart_put_char('\r');
|
||||
|
||||
drv_uart_put_char(c);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int fputs(const char *s, FILE *stream)
|
||||
{
|
||||
while (fputc(*s++, stream))
|
||||
;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int putc(int c, FILE *stream)
|
||||
{
|
||||
return fputc(c, stream);
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int putchar(int c)
|
||||
{
|
||||
return fputc(c, (void*)0x10);
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int puts(const char *s)
|
||||
{
|
||||
return fputs(s, (void*)0x10);
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
#include <stdarg.h> /* va_list, va_arg() */
|
||||
#include <stdio.h>
|
||||
|
||||
#include "do_printf.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* PRINTF You must write your own putchar()
|
||||
*****************************************************************************/
|
||||
static int vprintf_help(unsigned c, void **ptr){
|
||||
|
||||
ptr = ptr; /* to avoid unused varible warning */
|
||||
putchar(c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vsprintf_help(unsigned int c, void **ptr){
|
||||
|
||||
char *dst = *ptr;
|
||||
*dst++ = c;
|
||||
*ptr = dst;
|
||||
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int vsprintf(char *buffer, const char *fmt, va_list args){
|
||||
|
||||
int ret_val = do_printf(fmt, args, vsprintf_help, (void *)buffer);
|
||||
buffer[ret_val] = '\0';
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int sprintf(char *buffer, const char *fmt, ...){
|
||||
|
||||
va_list args;
|
||||
int ret_val;
|
||||
|
||||
va_start(args, fmt);
|
||||
ret_val = vsprintf(buffer, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int vprintf(const char *fmt, va_list args){
|
||||
|
||||
return do_printf(fmt, args, vprintf_help, (void *)0);
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int printf(const char *fmt, ...){
|
||||
|
||||
va_list args;
|
||||
int ret_val;
|
||||
|
||||
va_start(args, fmt);
|
||||
ret_val = vprintf(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return ret_val;
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
lib-y += qsort.o
|
|
@ -1,149 +0,0 @@
|
|||
//
|
||||
// qsort.c
|
||||
//
|
||||
// Quick sort
|
||||
//
|
||||
// Copyright (C) 2002 Michael Ringgaard. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// 3. Neither the name of the project nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
// SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#define CUTOFF 8
|
||||
|
||||
static void shortsort(char *lo, char *hi, unsigned width, int (*comp)(const void *, const void *));
|
||||
static void swap(char *p, char *q, unsigned int width);
|
||||
|
||||
__attribute__((used))
|
||||
void qsort(void *base, unsigned num, unsigned width, int (*comp)(const void *, const void *))
|
||||
{
|
||||
char *lo, *hi;
|
||||
char *mid;
|
||||
char *loguy, *higuy;
|
||||
unsigned size;
|
||||
char *lostk[30], *histk[30];
|
||||
int stkptr;
|
||||
|
||||
if (num < 2 || width == 0) return;
|
||||
stkptr = 0;
|
||||
|
||||
lo = base;
|
||||
hi = (char *) base + width * (num - 1);
|
||||
|
||||
recurse:
|
||||
size = (hi - lo) / width + 1;
|
||||
|
||||
if (size <= CUTOFF)
|
||||
{
|
||||
shortsort(lo, hi, width, comp);
|
||||
}
|
||||
else
|
||||
{
|
||||
mid = lo + (size / 2) * width;
|
||||
swap(mid, lo, width);
|
||||
|
||||
loguy = lo;
|
||||
higuy = hi + width;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
do { loguy += width; } while (loguy <= hi && comp(loguy, lo) <= 0);
|
||||
do { higuy -= width; } while (higuy > lo && comp(higuy, lo) >= 0);
|
||||
if (higuy < loguy) break;
|
||||
swap(loguy, higuy, width);
|
||||
}
|
||||
|
||||
swap(lo, higuy, width);
|
||||
|
||||
if (higuy - 1 - lo >= hi - loguy)
|
||||
{
|
||||
if (lo + width < higuy)
|
||||
{
|
||||
lostk[stkptr] = lo;
|
||||
histk[stkptr] = higuy - width;
|
||||
++stkptr;
|
||||
}
|
||||
|
||||
if (loguy < hi)
|
||||
{
|
||||
lo = loguy;
|
||||
goto recurse;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (loguy < hi)
|
||||
{
|
||||
lostk[stkptr] = loguy;
|
||||
histk[stkptr] = hi;
|
||||
++stkptr;
|
||||
}
|
||||
|
||||
if (lo + width < higuy)
|
||||
{
|
||||
hi = higuy - width;
|
||||
goto recurse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
--stkptr;
|
||||
if (stkptr >= 0)
|
||||
{
|
||||
lo = lostk[stkptr];
|
||||
hi = histk[stkptr];
|
||||
goto recurse;
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
static void shortsort(char *lo, char *hi, unsigned width, int (*comp)(const void *, const void *))
|
||||
{
|
||||
char *p, *max;
|
||||
|
||||
while (hi > lo)
|
||||
{
|
||||
max = lo;
|
||||
for (p = lo+width; p <= hi; p += width) if (comp(p, max) > 0) max = p;
|
||||
swap(max, hi, width);
|
||||
hi -= width;
|
||||
}
|
||||
}
|
||||
|
||||
static void swap(char *a, char *b, unsigned width)
|
||||
{
|
||||
char tmp;
|
||||
|
||||
if (a != b)
|
||||
{
|
||||
while (width--)
|
||||
{
|
||||
tmp = *a;
|
||||
*a++ = *b;
|
||||
*b++ = tmp;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
lib-y += memcpy.o
|
||||
lib-y += memmove.o
|
||||
lib-y += memset.o
|
||||
lib-y += strcat.o
|
||||
lib-y += strcasecmp.o
|
||||
lib-y += strcmp.o
|
||||
lib-y += strdup.o
|
||||
lib-y += strlen.o
|
||||
lib-y += strstr.o
|
||||
lib-y += strtoul.o
|
||||
lib-y += strupr.o
|
||||
lib-y += wchar.o
|
|
@ -1,10 +0,0 @@
|
|||
#include <string.h>
|
||||
|
||||
__attribute__((used))
|
||||
void *memcpy(void *dest, const void *src, size_t n)
|
||||
{
|
||||
while (n--)
|
||||
*(unsigned char *)dest++ = *(const unsigned char *)src++;
|
||||
|
||||
return dest;
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
#include <string.h>
|
||||
|
||||
__attribute__((used))
|
||||
void *memmove(void *dest, const void *src, size_t n)
|
||||
{
|
||||
char *destp = dest;
|
||||
const char *srcp = src;
|
||||
|
||||
if (srcp < destp)
|
||||
while (n--)
|
||||
destp[n] = srcp[n];
|
||||
else
|
||||
while (n--)
|
||||
*destp++ = *srcp++;
|
||||
|
||||
return dest;
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
#include <string.h>
|
||||
|
||||
__attribute__((used))
|
||||
void *memset(void *s, int c, size_t n)
|
||||
{
|
||||
while (n--)
|
||||
*(unsigned char *)s++ = c;
|
||||
|
||||
return s;
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
#include <string.h>
|
||||
|
||||
__attribute__((used))
|
||||
int strcasecmp(const char *s1, const char *s2)
|
||||
{
|
||||
while (*s1 == *s2 || (*s1 ^ 0x20) == *s2) {
|
||||
|
||||
if (!*s1)
|
||||
return 0;
|
||||
++s1;
|
||||
++s2;
|
||||
}
|
||||
|
||||
return *(unsigned char *)s1 - *(unsigned char *)s2;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int strncasecmp(const char *s1, const char *s2, size_t n)
|
||||
{
|
||||
while ((*s1 == *s2 || (*s1 ^ 0x20) == *s2) && --n) {
|
||||
|
||||
if (!*s1)
|
||||
return 0;
|
||||
++s1;
|
||||
++s2;
|
||||
}
|
||||
|
||||
return *(unsigned char *)s1 - *(unsigned char *)s2;
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
#include <string.h>
|
||||
|
||||
__attribute__((used))
|
||||
char *strcat(char *dest, const char *src)
|
||||
{
|
||||
char *destp = dest;
|
||||
|
||||
while (*destp)
|
||||
destp++;
|
||||
|
||||
while (*src)
|
||||
*destp++ = *src++;
|
||||
|
||||
*destp = '\0';
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
char *strncat(char *dest, const char *src, size_t n)
|
||||
{
|
||||
char *destp = dest;
|
||||
|
||||
while (*destp)
|
||||
destp++;
|
||||
|
||||
while (*src && n--)
|
||||
*destp++ = *src++;
|
||||
|
||||
*destp = '\0';
|
||||
|
||||
return dest;
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
#include <string.h>
|
||||
|
||||
__attribute__((used))
|
||||
int strcmp(const char *s1, const char *s2)
|
||||
{
|
||||
while (*s1 == *s2) {
|
||||
|
||||
if (!*s1)
|
||||
return 0;
|
||||
++s1;
|
||||
++s2;
|
||||
}
|
||||
|
||||
return *(unsigned char *)s1 - *(unsigned char *)s2;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int strncmp(const char *s1, const char *s2, size_t n)
|
||||
{
|
||||
while (*s1 == *s2 && --n) {
|
||||
|
||||
if (!*s1)
|
||||
return 0;
|
||||
++s1;
|
||||
++s2;
|
||||
}
|
||||
|
||||
return *(unsigned char *)s1 - *(unsigned char *)s2;
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
#include <string.h>
|
||||
|
||||
__attribute__((used))
|
||||
char *strcpy(char *dest, const void *src)
|
||||
{
|
||||
char *destp = dest;
|
||||
char *srcp = (char *)src;
|
||||
|
||||
while (*srcp)
|
||||
*destp++ = *srcp++;
|
||||
|
||||
*destp = '\0';
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
char *strncpy(char *dest, const void *src, size_t n)
|
||||
{
|
||||
char *destp = dest;
|
||||
char *srcp = (char *)src;
|
||||
|
||||
while (*srcp && n--)
|
||||
*destp++ = *srcp++;
|
||||
|
||||
if (n)
|
||||
*destp = '\0';
|
||||
|
||||
return dest;
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
__attribute__((used))
|
||||
char *strdup(const char *s)
|
||||
{
|
||||
int len = strlen(s);
|
||||
char *buf = malloc(len + 1);
|
||||
|
||||
if (buf) {
|
||||
|
||||
strncpy(buf, s, len);
|
||||
buf[len] = '\0';
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
char *strndup(const char *s, size_t n)
|
||||
{
|
||||
int len = strnlen(s, n);
|
||||
char *buf = malloc(len + 1);
|
||||
|
||||
if (buf) {
|
||||
|
||||
strncpy(buf, s, len);
|
||||
buf[len] = '\0';
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
#include <string.h>
|
||||
|
||||
__attribute__((used))
|
||||
size_t strlen(const char *s)
|
||||
{
|
||||
size_t n = 0;
|
||||
|
||||
while (*s++)
|
||||
n++;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
size_t strnlen(const char *s, size_t maxlen)
|
||||
{
|
||||
size_t n = 0;
|
||||
|
||||
while (*s++ && maxlen--)
|
||||
n++;
|
||||
|
||||
return n;
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
#include <string.h>
|
||||
|
||||
/* FIXME: LICENSE */
|
||||
__attribute__((used))
|
||||
char *strstr(const char *haystack, const char *needle)
|
||||
{
|
||||
const char *start_s1 = (void *)0;
|
||||
const char *in_s2 = (void *)0;
|
||||
|
||||
for (; *haystack != '\0'; haystack++) {
|
||||
|
||||
if (!start_s1) {
|
||||
|
||||
/* first char of match */
|
||||
if (*haystack == *needle) {
|
||||
|
||||
/* remember start of matching substring in haystack */
|
||||
start_s1 = haystack;
|
||||
in_s2 = needle + 1;
|
||||
/* done already? */
|
||||
if (*in_s2 == '\0')
|
||||
return (char*)start_s1;
|
||||
}
|
||||
/* continued mis-match
|
||||
else
|
||||
nothing ; */
|
||||
}
|
||||
else {
|
||||
|
||||
/* continued match */
|
||||
if (*haystack == *in_s2) {
|
||||
|
||||
in_s2++;
|
||||
/* done */
|
||||
if (*in_s2 == '\0')
|
||||
return (char*)start_s1;
|
||||
}
|
||||
else
|
||||
/* first char of mis-match */
|
||||
start_s1 = (void *)0;
|
||||
}
|
||||
}
|
||||
|
||||
return (void *)0;
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* FIXME: LICENSE */
|
||||
__attribute__((used))
|
||||
unsigned long int strtoul(const char *nptr, char **endptr, int base)
|
||||
{
|
||||
const char *s;
|
||||
unsigned long acc, cutoff;
|
||||
int c;
|
||||
int neg, any, cutlim;
|
||||
|
||||
s = nptr;
|
||||
do
|
||||
c = *s++;
|
||||
while (isspace(c));
|
||||
|
||||
if (c == '-') {
|
||||
|
||||
neg = 1;
|
||||
c = *s++;
|
||||
}
|
||||
else {
|
||||
neg = 0;
|
||||
if (c == '+')
|
||||
c = *s++;
|
||||
}
|
||||
|
||||
if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) {
|
||||
|
||||
c = s[1];
|
||||
s += 2;
|
||||
base = 16;
|
||||
}
|
||||
|
||||
if (base == 0)
|
||||
base = c == '0' ? 8 : 10;
|
||||
|
||||
#ifndef ULONG_MAX
|
||||
#define ULONG_MAX (unsigned long) -1
|
||||
#endif
|
||||
|
||||
cutoff = ULONG_MAX / (unsigned long)base;
|
||||
cutlim = ULONG_MAX % (unsigned long)base;
|
||||
|
||||
for (acc = 0, any = 0;; c = *s++) {
|
||||
|
||||
if (isdigit(c))
|
||||
c -= '0';
|
||||
|
||||
else if (isalpha(c))
|
||||
|
||||
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
|
||||
else
|
||||
break;
|
||||
|
||||
if (c >= base)
|
||||
break;
|
||||
|
||||
if (any < 0)
|
||||
continue;
|
||||
|
||||
// FIXME
|
||||
if (acc > cutoff || (acc == cutoff && c > cutlim)) {
|
||||
|
||||
any = -1;
|
||||
acc = ULONG_MAX;
|
||||
}
|
||||
else {
|
||||
any = 1;
|
||||
acc *= (unsigned long)base;
|
||||
acc += c;
|
||||
}
|
||||
}
|
||||
if (neg && any > 0)
|
||||
acc = -acc;
|
||||
|
||||
if (endptr != 0)
|
||||
*endptr = (char *)(any ? s - 1 : nptr);
|
||||
|
||||
return acc;
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
#include <string.h>
|
||||
|
||||
__attribute__((used))
|
||||
char *strupr(char *str)
|
||||
{
|
||||
char *str_iter = str;
|
||||
|
||||
while (*str_iter != 0)
|
||||
{
|
||||
if ((*str_iter >= 'a') && (*str_iter <= 'z'))
|
||||
*str_iter -= 0x20;
|
||||
++str_iter;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
|
@ -1,147 +0,0 @@
|
|||
#include <string.h>
|
||||
|
||||
__attribute__((used))
|
||||
wchar_t *wcscat(wchar_t *str_dst, const wchar_t *str_src)
|
||||
{
|
||||
wchar_t *dst_iter = str_dst;
|
||||
int i = 0;
|
||||
|
||||
while (*dst_iter != 0)
|
||||
++dst_iter;
|
||||
|
||||
while (str_src[i] != 0)
|
||||
{
|
||||
dst_iter[i] = str_src[i];
|
||||
++i;
|
||||
}
|
||||
|
||||
dst_iter[i] = 0;
|
||||
|
||||
return str_dst;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int wcscmp(const wchar_t *string1, const wchar_t *string2)
|
||||
{
|
||||
int i = 0;
|
||||
register wchar_t c1, c2;
|
||||
|
||||
while (1)
|
||||
{
|
||||
c1 = string1[i];
|
||||
c2 = string2[i];
|
||||
|
||||
if (c1 < c2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (c1 > c2)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((c1 == 0) || (c2 == 0))
|
||||
break;
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int wcsncmp(const wchar_t *string1, const wchar_t *string2, int count)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (i < count)
|
||||
{
|
||||
if (string1[i] < string2[i])
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (string1[i] > string2[i])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((string1[i] == 0) || (string2[i] == 0))
|
||||
break;
|
||||
++i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
wchar_t *wcscpy(wchar_t *str_dst, const wchar_t *str_src)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (str_src[i] != 0)
|
||||
{
|
||||
str_dst[i] = str_src[i];
|
||||
++i;
|
||||
}
|
||||
|
||||
str_dst[i] = 0;
|
||||
|
||||
return str_dst;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
wchar_t *wcsncpy(wchar_t *str_dst, const wchar_t *str_src, int count)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while ((str_src[i] != 0) && (i < count))
|
||||
{
|
||||
str_dst[i] = str_src[i];
|
||||
++i;
|
||||
}
|
||||
|
||||
str_dst[i] = 0;
|
||||
|
||||
return str_dst;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
int wcslen(const wchar_t *str)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (str[i] != 0)
|
||||
++i;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
wchar_t *wcsupr(wchar_t *str)
|
||||
{
|
||||
wchar_t *str_iter = str;
|
||||
|
||||
while (*str_iter != 0)
|
||||
{
|
||||
if ((*str_iter >= (wchar_t)'a') && (*str_iter <= (wchar_t)'z'))
|
||||
*str_iter -= 0x0020;
|
||||
++str_iter;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
__attribute__((used))
|
||||
wchar_t *wcslwr(wchar_t *str)
|
||||
{
|
||||
wchar_t *str_iter = str;
|
||||
|
||||
while (*str_iter != 0)
|
||||
{
|
||||
if ((*str_iter <= (wchar_t)'Z') && (*str_iter >= (wchar_t)'A'))
|
||||
*str_iter += 0x0020;
|
||||
++str_iter;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
|
@ -5,7 +5,7 @@ E-Mail : Archer Zhang <archer.zhang@wh-mx.com>
|
|||
******************************
|
||||
[1] 在bsp目录下,添加AE210P目录,这是Andes AE210P EVB(N1068A)的主目录;
|
||||
[2] 在libcpu目录下,添加nds32目录,这是Andes N10系列Core的体系目录;
|
||||
[3] 由于编译器和Libc的原因(我们使用的Libc位于AE210P/libc),修改了finsh.h文件的Line:74~75,如下
|
||||
[3] 由于编译器的原因,修改了finsh.h文件的Line:74~75,如下
|
||||
#if !(defined(__GNUC__) && defined(__x86_64__))
|
||||
//typedef unsigned int size_t; // 注释这个typedef
|
||||
#include <stddef.h> // 添加两个头文件包含
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
#ifndef OS_CPU_H
|
||||
#define OS_CPU_H
|
||||
|
||||
#include "nds32.h"
|
||||
/*
|
||||
* *********************************************************************************************************
|
||||
* * DATA TYPES
|
||||
* * (Compiler Specific)
|
||||
* *********************************************************************************************************
|
||||
* */
|
||||
typedef unsigned char BOOLEAN;
|
||||
typedef unsigned char INT8U; /* Unsigned 8 bit quantity */
|
||||
typedef signed char INT8S; /* Signed 8 bit quantity */
|
||||
typedef unsigned short INT16U; /* Unsigned 16 bit quantity */
|
||||
typedef signed short INT16S; /* Signed 16 bit quantity */
|
||||
typedef unsigned int INT32U; /* Unsigned 32 bit quantity */
|
||||
typedef signed int INT32S; /* Signed 32 bit quantity */
|
||||
typedef float FP32; /* Single precision floating point */
|
||||
typedef double FP64; /* Double precision floating point */
|
||||
|
||||
typedef unsigned long OS_STK; /* Each stack entry is 32-bit wide */
|
||||
typedef unsigned long OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */
|
||||
|
||||
void OS_CPU_IRQ_ISR(void); /* See OS_CPU_A.S */
|
||||
void OS_CPU_IRQ_ISR_Handler(void); /* See BSP code */
|
||||
|
||||
void OSCtxSw(void);
|
||||
void CtxSave(void);
|
||||
void CtxRestore(void);
|
||||
|
||||
void OS_DCache_Writeback(void *aVA, unsigned aSize);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue