Subversion Repositories HelenOS-historic

Compare Revisions

Ignore whitespace Rev 1391 → Rev 1392

/uspace/trunk/libadt/include/hash_table.h
File deleted
/uspace/trunk/libadt/include/list.h
File deleted
/uspace/trunk/libadt/include/fifo.h
File deleted
/uspace/trunk/libadt/generic/hash_table.c
File deleted
/uspace/trunk/libadt/generic/list.c
File deleted
/uspace/trunk/libadt/Makefile
File deleted
/uspace/trunk/kbd/generic/kbd.c
36,7 → 36,7
#include <arch/kbd.h>
#include <kbd.h>
#include <key_buffer.h>
#include <fifo.h>
#include <libadt/fifo.h>
 
#define NAME "KBD"
 
/uspace/trunk/kbd/generic/key_buffer.c
27,7 → 27,7
*/
 
#include <key_buffer.h>
#include <fifo.h>
#include <libadt/fifo.h>
 
#define KBD_BUFFER_SIZE 128 /**< Size of buffer for pressed keys */
 
/uspace/trunk/ns/Makefile
30,11 → 30,10
#
 
LIBC_PREFIX = ../libc
LIBADT_PREFIX = ../libadt
SOFTINT_PREFIX = ../softint
include $(LIBC_PREFIX)/Makefile.toolchain
 
LIBS = $(LIBADT_PREFIX)/libadt.a $(LIBC_PREFIX)/libc.a
LIBS = $(LIBC_PREFIX)/libc.a
 
## Sources
#
/uspace/trunk/fb/fb.c
44,14 → 44,10
#include <ipc/ns.h>
 
#include <kernel/errno.h>
#include <async.h>
 
 
#include "fb.h"
 
 
 
#define pl /*printf("FB:L:%d\n",(int)__LINE__);*/
 
#define EFB (-1)
 
#define DEFAULT_BGCOLOR 0x000080
79,11 → 75,8
 
 
 
 
 
int main(int argc, char *argv[])
static int init_fb(void)
{
__address fb_ph_addr;
unsigned int fb_width;
unsigned int fb_height;
91,10 → 84,10
unsigned int fb_scanline;
__address fb_addr;
int a=0;
int i,j,k;
int w;
char text[]="HelenOS Framebuffer driver\non Virtual Framebuffer\nVFB ";
 
 
if(!sysinfo_value("fb")) return -1;
fb_ph_addr=sysinfo_value("fb.address.physical");
fb_width=sysinfo_value("fb.width");
fb_height=sysinfo_value("fb.height");
104,9 → 97,9
fb_addr=ALIGN_UP(((__address)set_maxheapsize(USER_ADDRESS_SPACE_SIZE_ARCH>>1)),PAGE_SIZE);
 
 
 
map_physmem(task_get_id(),(void *)((__address)fb_ph_addr),(void *)fb_addr,
(fb_scanline*fb_height+PAGE_SIZE-1)>>PAGE_WIDTH,1);
(fb_scanline*fb_height+PAGE_SIZE-1)>>PAGE_WIDTH,1);
fb_init(0,fb_addr, fb_width, fb_height, fb_bpp, fb_scanline,
MAIN_BGCOLOR,MAIN_FGCOLOR,MAIN_LOGOCOLOR);
114,33 → 107,57
fb_putchar(0,'\n');
fb_putchar(0,' ');
 
for(i=0;i<H_NO_VFBS;i++)
for(j=0;j<V_NO_VFBS;j++) {
w = create_window(0,(fb_width/H_NO_VFBS)*i+SPACING,
(fb_height/V_NO_VFBS)*j+SPACING,(fb_width/H_NO_VFBS)-2*SPACING ,
(fb_height/V_NO_VFBS)-2*SPACING,mod_col(DEFAULT_BGCOLOR,/*i+j*H_NO_VFBS*/0),
mod_col(DEFAULT_FGCOLOR,/*i+j*H_NO_VFBS*/0),
mod_col(DEFAULT_LOGOCOLOR,/*i+j*H_NO_VFBS)*/0));
if( w== EFB)
return -1;
for(k=0;text[k];k++)
fb_putchar(w,text[k]);
fb_putchar(w,w+'0');
fb_putchar(w,'\n');
}
return 0;
}
 
{
int i,j;
int vfb_no = 1;
void client_connection(ipc_callid_t iid, ipc_call_t *icall)
{
ipc_callid_t callid;
ipc_call_t call;
int vfb = vfb_no++;
 
for(i=0;i<H_NO_VFBS;i++)
for(j=0;j<V_NO_VFBS;j++)
{
int w=create_window(0,(fb_width/H_NO_VFBS)*i+SPACING,
(fb_height/V_NO_VFBS)*j+SPACING,(fb_width/H_NO_VFBS)-2*SPACING ,
(fb_height/V_NO_VFBS)-2*SPACING,mod_col(DEFAULT_BGCOLOR,/*i+j*H_NO_VFBS*/0),
mod_col(DEFAULT_FGCOLOR,/*i+j*H_NO_VFBS*/0),
mod_col(DEFAULT_LOGOCOLOR,/*i+j*H_NO_VFBS)*/0));
if (vfb > 9) {
ipc_answer_fast(iid, ELIMIT, 0,0);
return;
}
ipc_answer_fast(iid, 0, 0, 0);
 
if(w==EFB) return -1;
while (1) {
callid = async_get_call(&call);
switch (IPC_GET_METHOD(call)) {
case IPC_M_PHONE_HUNGUP:
ipc_answer_fast(callid,0,0,0);
return; /* Exit thread */
 
{
char text[]="Hello, World from\nHelenOS Framebuffer driver\non Virtual Framebuffer\nVFB ";
int i;
for(i=0;text[i];i++) fb_putchar(w,text[i]);
fb_putchar(w,w+'0');
fb_putchar(w,'\n');
}
}
case FB_PUTCHAR:
ipc_answer_fast(callid,0,0,0);
fb_putchar(vfb,IPC_GET_ARG2(call));
break;
default:
ipc_answer_fast(callid,ENOENT,0,0);
}
}
}
 
 
int main(int argc, char *argv[])
{
ipc_call_t call;
ipc_callid_t callid;
char connected = 0;
150,53 → 167,16
ipcarg_t retval, arg1, arg2;
 
if(!sysinfo_value("fb")) return -1;
 
 
if ((res = ipc_connect_to_me(PHONE_NS, SERVICE_VIDEO, 0, &phonead)) != 0)
{
return -1;
};
init_fb();
 
while (1) {
static int vfb_no=1;
 
callid = ipc_wait_for_call(&call);
// printf("%s:Call phone=%lX..", NAME, call.in_phone_hash);
switch (IPC_GET_METHOD(call)&((1<<METHOD_WIDTH)-1)) {
case IPC_M_PHONE_HUNGUP:
// fb_putchar(4,((a++)&15)+'A');
retval = 0;
break;
case IPC_M_CONNECT_ME_TO:
retval = 0;
// fb_putchar(1,((a++)&15)+'A');
break;
case FB_GET_VFB:
retval = 0;
arg1 = vfb_no++;
// fb_putchar(2,((a++)&15)+'A');
break;
 
case FB_PUTCHAR:
retval = 0;
fb_putchar(IPC_GET_ARG1(call),IPC_GET_ARG2(call));
// fb_putchar(2,((a++)&15)+'A');
break;
 
default:
retval = ENOENT;
// fb_putchar(3,((a++)&15)+'A');
break;
}
 
if (! (callid & IPC_CALLID_NOTIFICATION)) {
ipc_answer_fast(callid, retval, arg1, arg2);
}
}
 
async_manager();
/* Never reached */
return 0;
}
/*
309,7 → 289,6
FB(item,fbaddress)[startbyte + 1] = GREEN(color, 8);
FB(item,fbaddress)[startbyte + 0] = BLUE(color, 8);
#endif
 
}
 
371,7 → 350,7
unsigned int y;
for (y = 0; y < FB(item,yres); y++)
{
clear_line(item,y); pl
clear_line(item,y);
}
}
 
553,14 → 532,14
}
 
FB(item,fbaddress) = (unsigned char *) addr; pl
FB(item,xres) = x; pl
FB(item,yres) = y; pl
FB(item,scanline) = scan; pl
FB(item,fbaddress) = (unsigned char *) addr;
FB(item,xres) = x;
FB(item,yres) = y;
FB(item,scanline) = scan;
FB(item,rows) = y / FONT_SCANLINES; pl
FB(item,columns) = x / COL_WIDTH; pl
FB(item,rows) = y / FONT_SCANLINES;
FB(item,columns) = x / COL_WIDTH;
 
FB(item,BGCOLOR)=BGCOLOR;
FB(item,FGCOLOR)=FGCOLOR;
567,9 → 546,9
FB(item,LOGOCOLOR)=LOGOCOLOR;
 
 
clear_screen(item); pl
draw_logo(item,FB(item,xres) - helenos_width, 0); pl
invert_cursor(item); pl
clear_screen(item);
draw_logo(item,FB(item,xres) - helenos_width, 0);
invert_cursor(item);
 
}
 
/uspace/trunk/libc/include/libadt/hash_table.h
0,0 → 1,80
/*
* Copyright (C) 2006 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - 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.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
 
#ifndef __HASH_TABLE_H__
#define __HASH_TABLE_H__
 
#include <libadt/list.h>
#include <unistd.h>
 
typedef unsigned long hash_count_t;
typedef unsigned long hash_index_t;
typedef struct hash_table hash_table_t;
typedef struct hash_table_operations hash_table_operations_t;
 
/** Hash table structure. */
struct hash_table {
link_t *entry;
hash_count_t entries;
hash_count_t max_keys;
hash_table_operations_t *op;
};
 
/** Set of operations for hash table. */
struct hash_table_operations {
/** Hash function.
*
* @param key Array of keys needed to compute hash index. All keys must be passed.
*
* @return Index into hash table.
*/
hash_index_t (* hash)(unsigned long key[]);
/** Hash table item comparison function.
*
* @param key Array of keys that will be compared with item. It is not necessary to pass all keys.
*
* @return true if the keys match, false otherwise.
*/
int (*compare)(unsigned long key[], hash_count_t keys, link_t *item);
 
/** Hash table item removal callback.
*
* @param item Item that was removed from the hash table.
*/
void (*remove_callback)(link_t *item);
};
 
#define hash_table_get_instance(item, type, member) list_get_instance((item), type, member)
 
extern int hash_table_create(hash_table_t *h, hash_count_t m, hash_count_t max_keys, hash_table_operations_t *op);
extern void hash_table_insert(hash_table_t *h, unsigned long key[], link_t *item);
extern link_t *hash_table_find(hash_table_t *h, unsigned long key[]);
extern void hash_table_remove(hash_table_t *h, unsigned long key[], hash_count_t keys);
 
#endif
/uspace/trunk/libc/include/libadt/list.h
0,0 → 1,185
/*
* Copyright (C) 2001-2004 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - 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.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
 
#ifndef __LIST_H__
#define __LIST_H__
 
#include<unistd.h>
 
#ifndef true
# define true 1
#endif
#ifndef false
# define false 0
#endif
 
typedef struct link link_t;
 
/** Doubly linked list head and link type. */
struct link {
link_t *prev; /**< Pointer to the previous item in the list. */
link_t *next; /**< Pointer to the next item in the list. */
};
 
/** Declare and initialize statically allocated list.
*
* @param name Name of the new statically allocated list.
*/
#define LIST_INITIALIZE(name) link_t name = { .prev = &name, .next = &name }
 
/** Initialize doubly-linked circular list link
*
* Initialize doubly-linked list link.
*
* @param link Pointer to link_t structure to be initialized.
*/
static inline void link_initialize(link_t *link)
{
link->prev = NULL;
link->next = NULL;
}
 
/** Initialize doubly-linked circular list
*
* Initialize doubly-linked circular list.
*
* @param head Pointer to link_t structure representing head of the list.
*/
static inline void list_initialize(link_t *head)
{
head->prev = head;
head->next = head;
}
 
/** Add item to the beginning of doubly-linked circular list
*
* Add item to the beginning of doubly-linked circular list.
*
* @param link Pointer to link_t structure to be added.
* @param head Pointer to link_t structure representing head of the list.
*/
static inline void list_prepend(link_t *link, link_t *head)
{
link->next = head->next;
link->prev = head;
head->next->prev = link;
head->next = link;
}
 
/** Add item to the end of doubly-linked circular list
*
* Add item to the end of doubly-linked circular list.
*
* @param link Pointer to link_t structure to be added.
* @param head Pointer to link_t structure representing head of the list.
*/
static inline void list_append(link_t *link, link_t *head)
{
link->prev = head->prev;
link->next = head;
head->prev->next = link;
head->prev = link;
}
 
/** Remove item from doubly-linked circular list
*
* Remove item from doubly-linked circular list.
*
* @param link Pointer to link_t structure to be removed from the list it is contained in.
*/
static inline void list_remove(link_t *link)
{
link->next->prev = link->prev;
link->prev->next = link->next;
link_initialize(link);
}
 
/** Query emptiness of doubly-linked circular list
*
* Query emptiness of doubly-linked circular list.
*
* @param head Pointer to link_t structure representing head of the list.
*/
static inline int list_empty(link_t *head)
{
return head->next == head ? true : false;
}
 
 
/** Split or concatenate headless doubly-linked circular list
*
* Split or concatenate headless doubly-linked circular list.
*
* Note that the algorithm works both directions:
* concatenates splitted lists and splits concatenated lists.
*
* @param part1 Pointer to link_t structure leading the first (half of the headless) list.
* @param part2 Pointer to link_t structure leading the second (half of the headless) list.
*/
static inline void headless_list_split_or_concat(link_t *part1, link_t *part2)
{
link_t *hlp;
 
part1->prev->next = part2;
part2->prev->next = part1;
hlp = part1->prev;
part1->prev = part2->prev;
part2->prev = hlp;
}
 
 
/** Split headless doubly-linked circular list
*
* Split headless doubly-linked circular list.
*
* @param part1 Pointer to link_t structure leading the first half of the headless list.
* @param part2 Pointer to link_t structure leading the second half of the headless list.
*/
static inline void headless_list_split(link_t *part1, link_t *part2)
{
headless_list_split_or_concat(part1, part2);
}
 
/** Concatenate two headless doubly-linked circular lists
*
* Concatenate two headless doubly-linked circular lists.
*
* @param part1 Pointer to link_t structure leading the first headless list.
* @param part2 Pointer to link_t structure leading the second headless list.
*/
static inline void headless_list_concat(link_t *part1, link_t *part2)
{
headless_list_split_or_concat(part1, part2);
}
 
#define list_get_instance(link,type,member) (type *)(((char *)(link))-((char *)&(((type *)NULL)->member)))
 
extern int list_member(const link_t *link, const link_t *head);
extern void list_concat(link_t *head1, link_t *head2);
 
#endif
/uspace/trunk/libc/include/libadt/fifo.h
0,0 → 1,115
/*
* Copyright (C) 2006 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - 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.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
 
/*
* This implementation of FIFO stores values in an array
* (static or dynamic). As such, these FIFOs have upper bound
* on number of values they can store. Push and pop operations
* are done via accessing the array through head and tail indices.
* Because of better operation ordering in fifo_pop(), the access
* policy for these two indices is to 'increment (mod size of FIFO)
* and use'.
*/
 
#ifndef __FIFO_H__
#define __FIFO_H__
 
#include <malloc.h>
 
typedef unsigned long fifo_count_t;
typedef unsigned long fifo_index_t;
 
/** Create and initialize static FIFO.
*
* FIFO is allocated statically.
* This macro is suitable for creating smaller FIFOs.
*
* @param name Name of FIFO.
* @param t Type of values stored in FIFO.
* @param itms Number of items that can be stored in FIFO.
*/
#define FIFO_INITIALIZE_STATIC(name, t, itms) \
struct { \
t fifo[(itms)]; \
fifo_count_t items; \
fifo_index_t head; \
fifo_index_t tail; \
} name = { \
.items = (itms), \
.head = 0, \
.tail = 0 \
}
 
/** Create and prepare dynamic FIFO.
*
* FIFO is allocated dynamically.
* This macro is suitable for creating larger FIFOs.
*
* @param name Name of FIFO.
* @param t Type of values stored in FIFO.
* @param itms Number of items that can be stored in FIFO.
*/
#define FIFO_INITIALIZE_DYNAMIC(name, t, itms) \
struct { \
t *fifo; \
fifo_count_t items; \
fifo_index_t head; \
fifo_index_t tail; \
} name = { \
.fifo = NULL, \
.items = (itms), \
.head = 0, \
.tail = 0 \
}
 
/** Pop value from head of FIFO.
*
* @param name FIFO name.
*
* @return Leading value in FIFO.
*/
#define fifo_pop(name) \
name.fifo[name.head = (name.head + 1) < name.items ? (name.head + 1) : 0]
 
/** Push value to tail of FIFO.
*
* @param name FIFO name.
* @param value Value to be appended to FIFO.
*
*/
#define fifo_push(name, value) \
name.fifo[name.tail = (name.tail + 1) < name.items ? (name.tail + 1) : 0] = (value)
 
/** Allocate memory for dynamic FIFO.
*
* @param name FIFO name.
*/
#define fifo_create(name) \
name.fifo = malloc(sizeof(*name.fifo) * name.items)
 
#endif
/uspace/trunk/libc/include/psthread.h
40,6 → 40,12
(c)->tls = (sysarg_t) (ptls);
#endif /* context_set */
 
typedef enum {
PS_TO_MANAGER,
PS_FROM_MANAGER,
PS_PREEMPT
} pschange_type;
 
typedef sysarg_t pstid_t;
 
struct psthread_data {
61,10 → 67,17
extern void context_restore(context_t *c) __attribute__ ((noreturn));
 
pstid_t psthread_create(int (*func)(void *), void *arg);
int psthread_schedule_next(void);
int psthread_join(pstid_t psthrid);
psthread_data_t * psthread_setup(tcb_t *tcb);
psthread_data_t * psthread_setup(void);
void psthread_teardown(psthread_data_t *pt);
int psthread_schedule_next_adv(pschange_type ctype);
void psthread_add_ready(pstid_t ptid);
void psthread_add_manager(pstid_t psthrid);
void psthread_remove_manager(void);
 
static inline int psthread_schedule_next() {
return psthread_schedule_next_adv(PS_PREEMPT);
}
 
 
#endif
/uspace/trunk/libc/include/ipc/ipc.h
33,6 → 33,7
#include <kernel/ipc/irq.h>
#include <libc.h>
#include <types.h>
#include <kernel/synch/synch.h>
 
typedef sysarg_t ipcarg_t;
typedef struct {
53,8 → 54,12
 
extern int ipc_call_sync(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t *result);
extern ipc_callid_t ipc_wait_for_call(ipc_call_t *data);
extern ipc_callid_t ipc_wait_cycle(ipc_call_t *call, uint32_t usec, int flags);
extern ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *data, uint32_t usec);
static inline ipc_callid_t ipc_wait_for_call(ipc_call_t *data)
{
return ipc_wait_for_call_timeout(data, SYNCH_NO_TIMEOUT);
}
extern ipc_callid_t ipc_trywait_for_call(ipc_call_t *data);
 
extern ipcarg_t ipc_answer_fast(ipc_callid_t callid, ipcarg_t retval, ipcarg_t arg1,
71,6 → 76,5
extern int ipc_register_irq(int irq, irq_code_t *code);
extern int ipc_unregister_irq(int irq);
extern int ipc_forward_fast(ipc_callid_t callid, int phoneid, int method, ipcarg_t arg1);
extern void _ipc_init(void);
 
#endif
/uspace/trunk/libc/generic/libadt/hash_table.c
0,0 → 1,170
/*
* Copyright (C) 2006 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - 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.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
 
/*
* This is an implementation of generic chained hash table.
*/
 
#include <libadt/hash_table.h>
#include <libadt/list.h>
#include <unistd.h>
#include <malloc.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
 
/** Create chained hash table.
*
* @param h Hash table structure. Will be initialized by this call.
* @param m Number of slots in the hash table.
* @param max_keys Maximal number of keys needed to identify an item.
* @param op Hash table operations structure.
* @return true on success
*/
int hash_table_create(hash_table_t *h, hash_count_t m, hash_count_t max_keys, hash_table_operations_t *op)
{
hash_count_t i;
 
assert(h);
assert(op && op->hash && op->compare);
assert(max_keys > 0);
h->entry = malloc(m * sizeof(link_t));
if (!h->entry) {
printf("cannot allocate memory for hash table\n");
return false;
}
memset((void *) h->entry, 0, m * sizeof(link_t));
for (i = 0; i < m; i++)
list_initialize(&h->entry[i]);
h->entries = m;
h->max_keys = max_keys;
h->op = op;
return true;
}
 
/** Insert item into hash table.
*
* @param h Hash table.
* @param hey Array of all keys necessary to compute hash index.
* @param item Item to be inserted into the hash table.
*/
void hash_table_insert(hash_table_t *h, unsigned long key[], link_t *item)
{
hash_index_t chain;
 
assert(item);
assert(h && h->op && h->op->hash && h->op->compare);
 
chain = h->op->hash(key);
assert(chain < h->entries);
list_append(item, &h->entry[chain]);
}
 
/** Search hash table for an item matching keys.
*
* @param h Hash table.
* @param key Array of all keys needed to compute hash index.
*
* @return Matching item on success, NULL if there is no such item.
*/
link_t *hash_table_find(hash_table_t *h, unsigned long key[])
{
link_t *cur;
hash_index_t chain;
 
assert(h && h->op && h->op->hash && h->op->compare);
 
chain = h->op->hash(key);
assert(chain < h->entries);
for (cur = h->entry[chain].next; cur != &h->entry[chain]; cur = cur->next) {
if (h->op->compare(key, h->max_keys, cur)) {
/*
* The entry is there.
*/
return cur;
}
}
return NULL;
}
 
/** Remove all matching items from hash table.
*
* For each removed item, h->remove_callback() is called.
*
* @param h Hash table.
* @param key Array of keys that will be compared against items of the hash table.
* @param keys Number of keys in the 'key' array.
*/
void hash_table_remove(hash_table_t *h, unsigned long key[], hash_count_t keys)
{
hash_index_t chain;
link_t *cur;
 
assert(h && h->op && h->op->hash && h->op->compare && h->op->remove_callback);
assert(keys <= h->max_keys);
if (keys == h->max_keys) {
 
/*
* All keys are known, hash_table_find() can be used to find the entry.
*/
cur = hash_table_find(h, key);
if (cur) {
list_remove(cur);
h->op->remove_callback(cur);
}
return;
}
/*
* Fewer keys were passed.
* Any partially matching entries are to be removed.
*/
for (chain = 0; chain < h->entries; chain++) {
for (cur = h->entry[chain].next; cur != &h->entry[chain]; cur = cur->next) {
if (h->op->compare(key, keys, cur)) {
link_t *hlp;
hlp = cur;
cur = cur->prev;
list_remove(hlp);
h->op->remove_callback(hlp);
continue;
}
}
}
}
/uspace/trunk/libc/generic/libadt/list.c
0,0 → 1,80
/*
* Copyright (C) 2004 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - 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.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
 
#include <libadt/list.h>
 
 
/** Check for membership
*
* Check whether link is contained in the list head.
* The membership is defined as pointer equivalence.
*
* @param link Item to look for.
* @param head List to look in.
*
* @return true if link is contained in head, false otherwise.
*
*/
int list_member(const link_t *link, const link_t *head)
{
int found = false;
link_t *hlp = head->next;
while (hlp != head) {
if (hlp == link) {
found = true;
break;
}
hlp = hlp->next;
}
return found;
}
 
 
/** Concatenate two lists
*
* Concatenate lists head1 and head2, producing a single
* list head1 containing items from both (in head1, head2
* order) and empty list head2.
*
* @param head1 First list and concatenated output
* @param head2 Second list and empty output.
*
*/
void list_concat(link_t *head1, link_t *head2)
{
if (list_empty(head2))
return;
 
head2->next->prev = head1->prev;
head2->prev->next = head1;
head1->prev->next = head2->next;
head1->prev = head2->prev;
list_initialize(head2);
}
/uspace/trunk/libc/generic/thread.c
33,6 → 33,7
#include <kernel/proc/uarg.h>
#include <psthread.h>
#include <string.h>
#include <async.h>
 
#include <stdio.h>
 
80,21 → 81,24
* directly.
*
* @param uarg Pointer to userspace argument structure.
*
* TODO: Thread stack pages memory leak
*/
void __thread_main(uspace_arg_t *uarg)
{
tcb_t *tcb;
/* This should initialize the area according to TLS specicification */
tcb = __make_tls();
__tcb_set(tcb);
psthread_setup(tcb);
psthread_data_t *pt;
 
pt = psthread_setup();
__tcb_set(pt->tcb);
async_create_manager();
 
uarg->uspace_thread_function(uarg->uspace_thread_arg);
free(uarg->uspace_stack);
free(uarg);
 
psthread_teardown(tcb->pst_data);
__free_tls(tcb);
async_destroy_manager();
psthread_teardown(pt);
 
thread_exit(0);
}
/uspace/trunk/libc/generic/libc.c
33,6 → 33,7
#include <psthread.h>
#include <io/stream.h>
#include <ipc/ipc.h>
#include <async.h>
 
void _exit(int status) {
thread_exit(status);
39,12 → 40,11
}
 
void __main(void) {
tcb_t *tcb;
tcb = __make_tls();
__tcb_set(tcb);
psthread_setup(tcb);
_ipc_init();
psthread_data_t *pt;
 
_async_init();
pt = psthread_setup();
__tcb_set(pt->tcb);
}
 
void __io_init(void) {
54,10 → 54,6
}
 
void __exit(void) {
tcb_t *tcb;
 
tcb = __tcb_get();
psthread_teardown(tcb->pst_data);
__free_tls(tcb);
psthread_teardown(__tcb_get()->pst_data);
_exit(0);
}
/uspace/trunk/libc/generic/psthread.c
33,24 → 33,34
#include <thread.h>
#include <stdio.h>
#include <kernel/arch/faddr.h>
#include <futex.h>
#include <assert.h>
 
 
#ifndef PSTHREAD_INITIAL_STACK_PAGES_NO
#define PSTHREAD_INITIAL_STACK_PAGES_NO 1
#endif
 
static LIST_INITIALIZE(ready_list);
static LIST_INITIALIZE(manager_list);
 
static void psthread_exit(void) __attribute__ ((noinline));
static void psthread_main(void);
 
static atomic_t psthread_futex = FUTEX_INITIALIZER;
 
/** Setup PSthread information into TCB structure */
psthread_data_t * psthread_setup(tcb_t *tcb)
psthread_data_t * psthread_setup()
{
psthread_data_t *pt;
tcb_t *tcb;
 
tcb = __make_tls();
if (!tcb)
return NULL;
 
pt = malloc(sizeof(*pt));
if (!pt) {
__free_tls(tcb);
return NULL;
}
 
62,6 → 72,7
 
void psthread_teardown(psthread_data_t *pt)
{
__free_tls(pt->tcb);
free(pt);
}
 
72,14 → 83,21
{
psthread_data_t *pt;
 
if (list_empty(&ready_list)) {
/* Wait on IPC queue etc... */
printf("Cannot exit!!!\n");
futex_down(&psthread_futex);
 
if (!list_empty(&ready_list))
pt = list_get_instance(ready_list.next, psthread_data_t, link);
else if (!list_empty(&manager_list))
pt = list_get_instance(manager_list.next, psthread_data_t, link);
else {
printf("Cannot find suitable psthread to run.\n");
_exit(0);
}
pt = list_get_instance(ready_list.next, psthread_data_t, link);
list_remove(&pt->link);
futex_up(&psthread_futex);
 
context_restore(&pt->ctx);
/* Never reached */
}
 
/** Function that is called on entry to new uspace thread */
98,24 → 116,47
 
/** Schedule next userspace pseudo thread.
*
* @param tomanager If true, we are switching to next ready manager thread
* (if none is found, thread is exited)
* @param frommanager If true, we are switching from manager thread
* @return 0 if there is no ready pseudo thread, 1 otherwise.
*/
int psthread_schedule_next(void)
int psthread_schedule_next_adv(pschange_type ctype)
{
psthread_data_t *pt;
int retval = 0;
futex_down(&psthread_futex);
 
if (list_empty(&ready_list))
return 0;
if (ctype == PS_PREEMPT && list_empty(&ready_list))
goto ret_0;
 
if (ctype == PS_FROM_MANAGER && list_empty(&ready_list)) {
goto ret_0;
}
assert(!(ctype == PS_TO_MANAGER && list_empty(&manager_list)));
 
pt = __tcb_get()->pst_data;
if (!context_save(&pt->ctx))
return 1;
if (!context_save(&pt->ctx))
return 1; // futex_up already done here
 
if (ctype == PS_PREEMPT)
list_append(&pt->link, &ready_list);
else if (ctype == PS_FROM_MANAGER)
list_append(&pt->link, &manager_list);
list_append(&pt->link, &ready_list);
pt = list_get_instance(ready_list.next, psthread_data_t, link);
if (ctype == PS_TO_MANAGER)
pt = list_get_instance(manager_list.next,psthread_data_t, link);
else
pt = list_get_instance(ready_list.next, psthread_data_t, link);
list_remove(&pt->link);
 
futex_up(&psthread_futex);
context_restore(&pt->ctx);
 
ret_0:
futex_up(&psthread_futex);
return retval;
}
 
/** Wait for uspace pseudo thread to finish.
142,7 → 183,6
retval = pt->retval;
 
free(pt->stack);
__free_tls(pt->tcb);
psthread_teardown((void *)pt);
 
return retval;
149,7 → 189,7
}
 
/**
* Create a userspace thread and append it to ready list.
* Create a userspace thread
*
* @param func Pseudo thread function.
* @param arg Argument to pass to func.
159,21 → 199,13
pstid_t psthread_create(int (*func)(void *), void *arg)
{
psthread_data_t *pt;
tcb_t *tcb;
 
tcb = __make_tls();
if (!tcb)
pt = psthread_setup();
if (!pt)
return 0;
 
pt = psthread_setup(tcb);
if (!pt) {
__free_tls(tcb);
return 0;
}
pt->stack = (char *) malloc(PSTHREAD_INITIAL_STACK_PAGES_NO*getpagesize());
 
if (!pt->stack) {
__free_tls(tcb);
psthread_teardown(pt);
return 0;
}
185,9 → 217,43
 
context_save(&pt->ctx);
context_set(&pt->ctx, FADDR(psthread_main), pt->stack, PSTHREAD_INITIAL_STACK_PAGES_NO*getpagesize(),
tcb);
pt->tcb);
 
return (pstid_t )pt;
}
 
/** Add a thread to ready list */
void psthread_add_ready(pstid_t psthrid)
{
psthread_data_t *pt;
 
pt = (psthread_data_t *) psthrid;
futex_down(&psthread_futex);
list_append(&pt->link, &ready_list);
futex_up(&psthread_futex);
}
 
return (pstid_t )pt;
/** Add a thread to manager list */
void psthread_add_manager(pstid_t psthrid)
{
psthread_data_t *pt;
 
pt = (psthread_data_t *) psthrid;
 
futex_down(&psthread_futex);
list_append(&pt->link, &manager_list);
futex_up(&psthread_futex);
}
 
/** Remove one manager from manager list */
void psthread_remove_manager()
{
futex_down(&psthread_futex);
if (list_empty(&manager_list)) {
printf("No manager found!.\n");
futex_up(&psthread_futex);
return;
}
list_remove(manager_list.next);
futex_up(&psthread_futex);
}
/uspace/trunk/libc/generic/ipc.c
57,13 → 57,8
LIST_INITIALIZE(dispatched_calls);
LIST_INITIALIZE(queued_calls);
 
static atomic_t ipc_futex;
static atomic_t ipc_futex = FUTEX_INITIALIZER;
 
void _ipc_init(void)
{
futex_initialize(&ipc_futex, 1);
}
 
int ipc_call_sync(int phoneid, ipcarg_t method, ipcarg_t arg1,
ipcarg_t *result)
{
252,25 → 247,25
}
 
 
/** Unconditionally wait for an IPC call.
/** One cycle of ipc wait for call call
*
* - dispatch ASYNC reoutines in the background
* @param call Space where the message is stored
* @param usec Timeout in microseconds
* @param flags Flags passed to SYS_IPC_WAIT (blocking, nonblocking)
* @return Callid of the answer.
*/
ipc_callid_t ipc_wait_for_call(ipc_call_t *call)
ipc_callid_t ipc_wait_cycle(ipc_call_t *call, uint32_t usec, int flags)
{
ipc_callid_t callid;
 
do {
try_dispatch_queued_calls();
try_dispatch_queued_calls();
callid = __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec, flags);
/* Handle received answers */
if (callid & IPC_CALLID_ANSWERED)
handle_answer(callid, call);
 
callid = __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, SYNCH_NO_TIMEOUT, SYNCH_BLOCKING);
/* Handle received answers */
if (callid & IPC_CALLID_ANSWERED)
handle_answer(callid, call);
} while (callid & IPC_CALLID_ANSWERED);
 
return callid;
}
 
286,12 → 281,7
ipc_callid_t callid;
 
do {
try_dispatch_queued_calls();
 
callid = __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec, SYNCH_BLOCKING);
/* Handle received answers */
if (callid & IPC_CALLID_ANSWERED)
handle_answer(callid, call);
callid = ipc_wait_cycle(call, usec, SYNCH_BLOCKING);
} while (callid & IPC_CALLID_ANSWERED);
 
return callid;
308,12 → 298,7
ipc_callid_t callid;
 
do {
try_dispatch_queued_calls();
 
callid = __SYSCALL3(SYS_IPC_WAIT, (sysarg_t)call, SYNCH_NO_TIMEOUT, SYNCH_NON_BLOCKING);
/* Handle received answers */
if (callid & IPC_CALLID_ANSWERED)
handle_answer(callid, call);
callid = ipc_wait_cycle(call, SYNCH_NO_TIMEOUT, SYNCH_NON_BLOCKING);
} while (callid & IPC_CALLID_ANSWERED);
 
return callid;
/uspace/trunk/libc/generic/async.c
26,52 → 26,305
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
ipc_wait_t call_func(args)
/**
* Asynchronous library
*
* The aim of this library is facilitating writing programs utilizing
* the asynchronous nature of Helenos IPC, yet using a normal way
* of programming.
*
* You should be able to write very simple multithreaded programs,
* the async framework will automatically take care of most synchronization
* problems.
*
* Default semantics:
* - send() - send asynchronously. If the kernel refuses to send more
* messages, [ try to get responses from kernel, if nothing
* found, might try synchronous ]
*
* Example of use:
*
* 1) Multithreaded client application
* create_thread(thread1);
* create_thread(thread2);
* ...
*
* thread1() {
* conn = ipc_connect_me_to();
* c1 = send(conn);
* c2 = send(conn);
* wait_for(c1);
* wait_for(c2);
* }
*
*
* 2) Multithreaded server application
* main() {
* wait_for_connection(new_connection);
* }
*
*
* new_connection(int connection) {
* accept(connection);
* msg = get_msg();
* handle(msg);
* answer(msg);
*
* msg = get_msg();
* ....
* }
*/
#include <futex.h>
#include <async.h>
#include <psthread.h>
#include <stdio.h>
#include <libadt/hash_table.h>
#include <libadt/list.h>
#include <ipc/ipc.h>
#include <assert.h>
#include <errno.h>
 
static atomic_t conn_futex = FUTEX_INITIALIZER;
static hash_table_t conn_hash_table;
 
typedef struct {
link_t link;
ipc_callid_t callid;
ipc_call_t call;
} msg_t;
 
typedef struct {
link_t link;
ipcarg_t in_phone_hash; /**< Incoming phone hash. */
link_t msg_queue; /**< Messages that should be delivered to this thread */
pstid_t ptid; /**< Thread associated with this connection */
int active; /**< If this thread is currently active */
int opened; /* If the connection was accepted */
/* Structures for connection opening packet */
ipc_callid_t callid;
ipc_call_t call;
} connection_t;
 
__thread connection_t *PS_connection;
 
/* Hash table functions */
 
#define ASYNC_HASH_TABLE_CHAINS 32
 
static hash_index_t conn_hash(unsigned long *key)
{
assert(key);
return ((*key) >> 4) % ASYNC_HASH_TABLE_CHAINS;
}
 
ipc_wait_t fire_function(args)
static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item)
{
stack = malloc(stacksize);
setup(stack);
add_to_list_of_ready_funcs(stack);
if (threads_waiting_for_message)
send_message_to_self_to_one_up();
connection_t *hs;
 
hs = hash_table_get_instance(item, connection_t, link);
return key[0] == hs->in_phone_hash;
}
 
void discard_result(ipc_wait_t funcid)
static void conn_remove(link_t *item)
{
free(hash_table_get_instance(item, connection_t, link));
}
 
int wait_result(ipc_wait_t funcid);
 
/** Operations for NS hash table. */
static hash_table_operations_t conn_hash_table_ops = {
.hash = conn_hash,
.compare = conn_compare,
.remove_callback = conn_remove
};
 
/** Try to route a call to an appropriate connection thread
*
*/
static int route_call(ipc_callid_t callid, ipc_call_t *call)
{
save_context(self);
restart:
if result_available() {
if in_list_of_ready(self):
tear_off_list(self);
return retval;
connection_t *conn;
msg_t *msg;
link_t *hlp;
unsigned long key;
 
futex_down(&conn_futex);
 
key = call->in_phone_hash;
hlp = hash_table_find(&conn_hash_table, &key);
if (!hlp) {
futex_up(&conn_futex);
return 0;
}
add_to_waitlist_of(funcid);
conn = hash_table_get_instance(hlp, connection_t, link);
 
take_something_from_list_of_ready();
if something {
restore_context(something);
} else { /* nothing */
wait_for_call();
if (answer) {
mark_result_ready();
put_waiting_thread_to_waitlist();
msg = malloc(sizeof(*msg));
msg->callid = callid;
msg->call = *call;
list_append(&msg->link, &conn->msg_queue);
if (!conn->active) {
conn->active = 1;
psthread_add_ready(conn->ptid);
}
 
goto restart;
}
futex_up(&conn_futex);
 
return 1;
}
 
ipc_callid_t async_get_call(ipc_call_t *call)
{
msg_t *msg;
ipc_callid_t callid;
connection_t *conn;
futex_down(&conn_futex);
 
conn = PS_connection;
/* If nothing in queue, wait until something appears */
if (list_empty(&conn->msg_queue)) {
conn->active = 0;
psthread_schedule_next_adv(PS_TO_MANAGER);
}
msg = list_get_instance(conn->msg_queue.next, msg_t, link);
list_remove(&msg->link);
callid = msg->callid;
*call = msg->call;
free(msg);
futex_up(&conn_futex);
return callid;
}
 
void client_connection(ipc_callid_t callid, ipc_call_t *call)
{
printf("Got connection - no handler.\n");
_exit(1);
}
 
int ipc_call_sync(args)
static int connection_thread(void *arg)
{
return ipc_wait(call_func(args));
/* Setup thread local connection pointer */
PS_connection = (connection_t *)arg;
client_connection(PS_connection->callid, &PS_connection->call);
 
futex_down(&conn_futex);
/* TODO: remove myself from connection hash table */
futex_up(&conn_futex);
/* TODO: answer all unanswered messages in queue with
* EHANGUP */
}
 
/** Create new thread for a new connection
*
* Creates new thread for connection, fills in connection
* structures and inserts it into the hash table, so that
* later we can easily do routing of messages to particular
* threads.
*/
static void new_connection(ipc_callid_t callid, ipc_call_t *call)
{
pstid_t ptid;
connection_t *conn;
unsigned long key;
 
conn = malloc(sizeof(*conn));
if (!conn) {
ipc_answer_fast(callid, ENOMEM, 0, 0);
return;
}
conn->in_phone_hash = IPC_GET_ARG3(*call);
list_initialize(&conn->msg_queue);
conn->opened = 0;
conn->ptid = psthread_create(connection_thread, conn);
conn->callid = callid;
conn->call = *call;
conn->active = 1; /* We will activate it asap */
list_initialize(&conn->link);
if (!conn->ptid) {
free(conn);
ipc_answer_fast(callid, ENOMEM, 0, 0);
return;
}
key = conn->in_phone_hash;
futex_down(&conn_futex);
/* Add connection to hash table */
hash_table_insert(&conn_hash_table, &key, &conn->link);
futex_up(&conn_futex);
 
psthread_add_ready(conn->ptid);
}
 
/** Handle call to a task */
static void handle_call(ipc_callid_t callid, ipc_call_t *call)
{
if (route_call(callid, call))
return;
 
switch (IPC_GET_METHOD(*call)) {
case IPC_M_INTERRUPT:
break;
case IPC_M_CONNECT_ME_TO:
/* Open new connection with thread etc. */
new_connection(callid, call);
break;
default:
ipc_answer_fast(callid, EHANGUP, 0, 0);
}
}
 
/** Endless loop dispatching incoming calls and answers */
int async_manager()
{
ipc_call_t call;
ipc_callid_t callid;
 
while (1) {
if (psthread_schedule_next_adv(PS_FROM_MANAGER)) {
futex_up(&conn_futex); /* conn_futex is always held
* when entering manager thread
*/
continue;
}
callid = ipc_wait_cycle(&call,SYNCH_NO_TIMEOUT,SYNCH_BLOCKING);
 
if (callid & IPC_CALLID_ANSWERED)
continue;
handle_call(callid, &call);
}
}
 
static int async_manager_thread(void *arg)
{
futex_up(&conn_futex); /* conn_futex is always locked when entering
* manager */
async_manager();
}
 
/** Add one manager to manager list */
void async_create_manager(void)
{
pstid_t ptid;
 
ptid = psthread_create(async_manager_thread, NULL);
psthread_add_manager(ptid);
}
 
/** Remove one manager from manager list */
void async_destroy_manager(void)
{
psthread_remove_manager();
}
 
/** Initialize internal structures needed for async manager */
int _async_init(void)
{
if (!hash_table_create(&conn_hash_table, ASYNC_HASH_TABLE_CHAINS, 1, &conn_hash_table_ops)) {
printf("%s: cannot create hash table\n", "async");
return ENOMEM;
}
}
/uspace/trunk/libc/Makefile
62,7 → 62,10
malloc/malloc.c \
generic/psthread.c \
generic/sysinfo.c \
generic/ipc.c
generic/ipc.c \
generic/async.c \
generic/libadt/list.o \
generic/libadt/hash_table.o
 
ARCH_SOURCES += \
arch/$(ARCH)/src/entry.s \
79,12 → 82,11
ln -sfn ../../../kernel/generic/include include/kernel
ln -sfn kernel/arch include/arch
ln -sfn ../arch/$(ARCH)/include include/libarch
ln -sfn ../../libadt/include include/libadt
 
-include Makefile.depend
 
clean:
-rm -f include/kernel include/arch include/libarch include/libadt libc.a arch/$(ARCH)/_link.ld Makefile.depend
-rm -f include/kernel include/arch include/libarch libc.a arch/$(ARCH)/_link.ld Makefile.depend
find generic/ arch/$(ARCH)/ -name '*.o' -follow -exec rm \{\} \;
 
depend: kerninc
91,7 → 93,7
-makedepend $(DEFS) $(CFLAGS) -f - $(ARCH_SOURCES) $(GENERIC_SOURCES) > Makefile.depend 2> /dev/null
 
libc.a: depend $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
$(AR) rc libc.a $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
$(AR) rc libc.a $(LIBS) $(ARCH_OBJECTS) $(GENERIC_OBJECTS)
 
arch/$(ARCH)/_link.ld: arch/$(ARCH)/_link.ld.in
$(CC) $(DEFS) $(CFLAGS) -E -x c $< | grep -v "^\#" > $@
/uspace/trunk/Makefile
35,8 → 35,8
libc \
softint \
softfloat \
libadt \
init \
test \
ns \
fb