From 37b6643df2df7d784a31ca73f7bb90dc109c2401 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 15 Dec 2005 07:26:47 +0000 Subject: removing PDP source (except debian files) before import of PDP 0.12.4 svn path=/trunk/externals/pdp/; revision=4217 --- system/kernel/pdp_packet2.c | 623 -------------------------------------------- 1 file changed, 623 deletions(-) delete mode 100644 system/kernel/pdp_packet2.c (limited to 'system/kernel/pdp_packet2.c') diff --git a/system/kernel/pdp_packet2.c b/system/kernel/pdp_packet2.c deleted file mode 100644 index 3717a77..0000000 --- a/system/kernel/pdp_packet2.c +++ /dev/null @@ -1,623 +0,0 @@ -/* - * Pure Data Packet system implementation: Packet Manager - * Copyright (c) by Tom Schouten - * - * This program 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 2 of the License, or - * (at your option) any later version. - * - * This program 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - - - -#include -#include -#include -#include -#include "pdp_post.h" -#include "pdp_packet.h" -#include "pdp_mem.h" -#include "pdp_list.h" -#include "pdp_type.h" -#include "pdp_debug.h" - - -/* packet implementation. contains class and packet (instance) handling - - some notes on packet operations. - copy ro/rw and unregister are relatively straightforward - packet creation can be done in 2 ways in this interface: - create + reuse - however, these methods should only be called by specific factory - methods, so the user should only create packets using pdp_factory_newpacket - - reuse or create is thus the responsability of the factory methods for - each packet type (class) implementation - - -*/ - - -/* NOTE: - the packet pool methods are called within the pool locks. this probably - needs to change, because it will cause deadlocks for container packets (fobs) */ - - -/* new implementation: probably just a minor adjustment: add the reuse fifo attached - to type desc symbol name - need to check and possibly eliminate hacks for non-pure packets - - pdp_packet_new: - LOCK - 1. check reuse fifo - 2. empty -> create packet+return (search array) - 3. element -> check if type is correct, yes->pop+return, no->goto 1. - UNLOCK - 4. wakeup - - pdp_packet_mark_unused - - 1. check refcount. if > 1 dec + exit - 2. if 1 put packet to sleep - 3. dec refcount - 4. add to reuse fifo (no fifo -> create) - - pdp_packet_delete: analogous to mark_unused - pdp_packet_copy_ro/rw: analogous to new - -*/ - - -/* the pool */ -#define PDP_INITIAL_POOL_SIZE 64 -static int pdp_pool_size; -static t_pdp** pdp_pool; - -/* mutex: protects the pool and reuse lists attached to symbols */ -static pthread_mutex_t pdp_pool_mutex; -#define LOCK pthread_mutex_lock (&pdp_pool_mutex) -#define UNLOCK pthread_mutex_unlock (&pdp_pool_mutex) - -/* the list of classes */ -static t_pdp_list *class_list; - -/* debug */ -void -pdp_packet_print_debug(int packet) -{ - t_pdp *h = pdp_packet_header(packet); - pdp_post("debug info for packet %d", packet); - if (!h){ - pdp_post("invalid packet"); - } - else{ - pdp_post ("\ttype: %d", h->type); - pdp_post ("\tdesc: %s", h->desc ? h->desc->s_name : "unknown"); - pdp_post ("\tsize: %d", h->size); - pdp_post ("\tflags: %x", h->flags); - pdp_post ("\tusers: %d", h->users); - pdp_post ("\tclass: %x", h->theclass); - } -} - - - -/* setup methods */ - -void -pdp_packet_setup(void) -{ - - pdp_pool_size = PDP_INITIAL_POOL_SIZE; - pdp_pool = (t_pdp **)pdp_alloc(PDP_INITIAL_POOL_SIZE * sizeof(t_pdp *)); - bzero(pdp_pool, pdp_pool_size * sizeof(t_pdp *)); - class_list = pdp_list_new(0); - pthread_mutex_init(&pdp_pool_mutex, NULL); -} - -/* class methods */ -t_pdp_class *pdp_class_new(t_pdp_symbol *type, t_pdp_factory_method create){ - t_pdp_class *c = (t_pdp_class *)pdp_alloc(sizeof(t_pdp_class)); - memset(c, 0, sizeof(t_pdp_class)); - c->create = create; - c->type = type; // set type - pdp_list_add(class_list, a_pointer, (t_pdp_word)((void *)c)); - return c; -} - -/* the packet factory */ -int pdp_factory_newpacket(t_pdp_symbol *type) -{ - int p; - t_pdp_class *c; - t_pdp_atom *a = class_list->first; - - /* try to reuse first - THINK: should this be the responsability of the type specific constructors, - or should a packet allways be reusable (solution: depends on what the cleanup method returns??) - */ - p = pdp_packet_reuse(type); - if (-1 != p) return p; - - - /* call class constructor */ - while(a){ - c = (t_pdp_class *)(a->w.w_pointer); - if (c->type && pdp_type_description_match(type, c->type)){ - //pdp_post("method %x, type %s", c->create, type->s_name); - return (c->create) ? (*c->create)(type) : -1; - } - a = a->next; - } - return -1; -} - -static void -_pdp_pool_expand_nolock(void){ - int i; - - /* double the size */ - int new_pool_size = pdp_pool_size << 1; - t_pdp **new_pool = (t_pdp **)pdp_alloc(new_pool_size * sizeof(t_pdp *)); - bzero(new_pool, new_pool_size * sizeof(t_pdp *)); - memcpy(new_pool, pdp_pool, pdp_pool_size * sizeof(t_pdp *)); - pdp_dealloc(pdp_pool); - pdp_pool = new_pool; - pdp_pool_size = new_pool_size; -} - - - - -/* private _pdp_packet methods */ - -/* packets can only be created and destroyed using these 2 methods */ -/* it updates the mem usage and total packet count */ - -static void -_pdp_packet_dealloc_nolock(t_pdp *p) -{ - /* free memory */ - pdp_dealloc (p); -} - -static t_pdp* -_pdp_packet_alloc_nolock(unsigned int datatype, unsigned int datasize) -{ - unsigned int totalsize = datasize + PDP_HEADER_SIZE; - t_pdp *p = (t_pdp *)pdp_alloc(totalsize); - if (p){ - memset(p, 0, PDP_HEADER_SIZE); //initialize header to 0 - p->type = datatype; - p->size = totalsize; - p->users = 1; - } - return p; -} - - -/* create a new packet and expand pool if necessary */ -static int -_pdp_packet_create_nolock(unsigned int datatype, unsigned int datasize) -{ - int p = 0; - while(1){ - for (; p < pdp_pool_size; p++){ - if (!pdp_pool[p]){ - /* found slot to store packet*/ - t_pdp *header = _pdp_packet_alloc_nolock(datatype, datasize); - if (!header) return -1; // error allocating packet - pdp_pool[p] = header; - return p; - } - } - /* no slot found, expand pool */ - _pdp_pool_expand_nolock(); - } -} - - -void -pdp_packet_destroy(void) -{ - int i = 0; - /* dealloc all the data in object stack */ - pdp_post("DEBUG: pdp_packet_destroy: clearing object pool."); - while ((i < pdp_pool_size) && (pdp_pool[i])) _pdp_packet_dealloc_nolock(pdp_pool[i++]); -} - - - - - - - - -/* public pool operations: have to be thread safe so each entry point - locks the mutex */ - - -/* create a new packet. - this should only be used by type specific factory methods, and only if the - reuse method fails, since it will always create a new packet */ -int -pdp_packet_create(unsigned int datatype, unsigned int datasize /*without header*/) -{ - int packet; - LOCK; - packet = _pdp_packet_create_nolock(datatype, datasize); - UNLOCK; - return packet; -} - - -/* return a new packet. - it tries to reuse a packet based on - 1. matching data size - 2. abscence of destructor (which SHOULD mean there are no enclosed references) - - it obviously can't use the reuse fifo tagged to a symbolic type description - - ALWAYS USE pdp_packet_reuse BEFORE calling pdp_packet_new if possible - use both ONLY IN CONSTRUCTORS !!! - - use pdp_packet_factory to create packets as a "user" - - this is a summary of all internal packet creation mechanisms: - - -> pdp_packet_reuse, which uses symbolic type descriptions, and should work for all packet types - it returns an initialized container (meta = correct, data = garbage) - - -> pdp_packet_new, which only works for non-pure packets, and reuses packets based on data type - it returns a pure packet (meta + data = garbage) - - -> pdp_packet_create, like pdp_packet_new, only it always creates a new packet - - - -*/ - -int -pdp_packet_new(unsigned int datatype, unsigned int datasize) -{ - t_pdp *header; - int packet; - LOCK; - for (packet = 0; packet < pdp_pool_size; packet++){ - header = pdp_pool[packet]; - /* check data size */ - if (header - && header->users == 0 - && header->size == datasize + PDP_HEADER_SIZE - && !(header->theclass && header->theclass->cleanup)){ - - /* ok, got one. initialize */ - memset(header, 0, PDP_HEADER_SIZE); - header->users = 1; - header->type = datatype; - header->size = datasize + PDP_HEADER_SIZE; - - UNLOCK; //EXIT1 - return packet; - } - } - - /* no usable non-pure packet found, create a new one */ - - UNLOCK; //EXIT2 - return pdp_packet_create(datatype, datasize); - - - -} - - -/* internal method to add a packet to a packet type - description symbol's unused packet fifo */ -void -_pdp_packet_save_nolock(int packet) -{ - t_pdp *header = pdp_packet_header(packet); - t_pdp_symbol *s; - PDP_ASSERT(header); - PDP_ASSERT(header->users == 0); - PDP_ASSERT(header->desc); - s = header->desc; - if (!s->s_reusefifo) s->s_reusefifo = pdp_list_new(0); - pdp_list_add(s->s_reusefifo, a_packet, (t_pdp_word)packet); -} - -/* this will revive a packet matching a certain type description - no wildcards are allowed */ -int -pdp_packet_reuse(t_pdp_symbol *type_description) -{ - int packet = -1; - t_pdp *header = 0; - t_pdp_list *l = 0; - LOCK; - if (!type_description || !(l = type_description->s_reusefifo)) goto exit; - while(l->elements){ - packet = pdp_list_pop(l).w_packet; - header = pdp_packet_header(packet); - - /* check if reuse fifo is consistent (packet unused + correct type) - packet could be deleted and replaced with another one, or - revived without the index updated (it's a "hint cache") */ - - if (header->users == 0){ - /* check if type matches */ - if (pdp_type_description_match(header->desc, type_description)){ - header->users++; // revive - goto exit; - } - /* if not, add the packet to the correct reuse fifo */ - else{ - _pdp_packet_save_nolock(packet); - } - } - - /* remove dangling refs */ - header = 0; - packet = -1; - } - - exit: - UNLOCK; - if (header && header->theclass && header->theclass->wakeup){ - header->theclass->wakeup(header); // revive if necessary - } - return packet; -} - -/* find all unused packets in pool, marked as used (to protect from other reapers) - and return them as a list. non-pure packets are not revived */ - - - - - -/* this returns a copy of a packet for read only access. - (increases refcount of the packet -> packet will become readonly if it was - writable, i.e. had rc=1 */ - -int -pdp_packet_copy_ro(int handle) -{ - t_pdp* header; - - if (header = pdp_packet_header(handle)){ - PDP_ASSERT(header->users); // consistency check - LOCK; - header->users++; // increment reference count - UNLOCK; - } - else handle = -1; - return handle; -} - -/* clone a packet: create a new packet with the same - type as the source packet */ - -int -pdp_packet_clone_rw(int handle) -{ - t_pdp* header; - int new_handle = -1; - - - if (header = pdp_packet_header(handle)){ - /* consistency checks */ - PDP_ASSERT(header->users); - PDP_ASSERT(header->desc); - - /* first try to reuse old packet */ - new_handle = pdp_packet_reuse(header->desc); - - /* if this failed, create a new one using the central packet factory method */ - if (-1 == new_handle) new_handle = pdp_factory_newpacket(header->desc); - } - - return new_handle; -} - -/* return a copy of a packet (clone + copy data) */ -int -pdp_packet_copy_rw(int handle) -{ - t_pdp *header, *new_header; - int new_handle = -1; - - if (!(header = pdp_packet_header(handle))) return -1; - - /* check if we are allowed to copy */ - if (header->flags & PDP_FLAG_DONOTCOPY) return -1; - - /* get target packet */ - new_handle = pdp_packet_clone_rw(handle); - if (-1 == new_handle) return -1; - new_header = pdp_packet_header(new_handle); - - /* if there is a copy method, use that one */ - if (header->theclass && header->theclass->copy){ - header->theclass->copy(header, new_header); - } - - /* otherwize copy the data verbatim */ - else { - memcpy(pdp_packet_data(new_handle), - pdp_packet_data(handle), - pdp_packet_data_size(handle)); - } - - return new_handle; - -} - - -/* decrement refcount */ -void pdp_packet_mark_unused(int handle) -{ - t_pdp *header; - if (!(header = pdp_packet_header(handle))) return; - - PDP_ASSERT(header->users); // consistency check - - LOCK; - - /* just decrement refcount */ - if (header->users > 1){ - header->users--; - } - - /* put packet to sleep if refcount 1->0 */ - else { - if (header->theclass && header->theclass->sleep){ - /* call sleep method (if any) outside of lock - while the packet is still alive, so it won't be - acclaimed by another thread */ - UNLOCK; - header->theclass->sleep(header); - LOCK; - } - /* clear refcount & save in fifo for later use */ - header->users = 0; - if (header->desc) // sleep could have destructed packet.. - _pdp_packet_save_nolock(handle); - } - - UNLOCK; -} - - - -/* delete a packet. rc needs to be == 1 */ -void pdp_packet_delete(int handle) -{ - t_pdp *header; - header = pdp_packet_header(handle); - PDP_ASSERT(header); - PDP_ASSERT(header->users == 1); // consistency check - - LOCK; - - if (header->theclass && header->theclass->cleanup){ - /* call cleanup method (if any) outside of lock - while the packet is still alive, so it won't be - acclaimed by another thread */ - UNLOCK; - header->theclass->cleanup(header); - LOCK; - } - - /* delete the packet */ - pdp_pool[handle] = 0; - _pdp_packet_dealloc_nolock(header); - - - UNLOCK; -} - - - - - - - -/* public data access methods */ - -t_pdp* -pdp_packet_header(int handle) -{ - if ((handle >= 0) && (handle < pdp_pool_size)) return pdp_pool[handle]; - else return 0; -} - -void* -pdp_packet_subheader(int handle) -{ - t_pdp* header = pdp_packet_header(handle); - if (!header) return 0; - return (void *)(&header->info.raw); -} - -void* -pdp_packet_data(int handle) -{ - t_pdp *h; - if ((handle >= 0) && (handle < pdp_pool_size)) - { - h = pdp_pool[handle]; - if (!h) return 0; - return (char *)(h) + PDP_HEADER_SIZE; - } - else return 0; -} - -int -pdp_packet_data_size(int handle) -{ - t_pdp *h; - if ((handle >= 0) && (handle < pdp_pool_size)) - { - h = pdp_pool[handle]; - if (!h) return 0; - return h->size - PDP_HEADER_SIZE; - } - else return 0; -} - - - - -int pdp_packet_writable(int packet) /* returns true if packet is writable */ -{ - t_pdp *h = pdp_packet_header(packet); - if (!h) return 0; - return (h->users == 1); -} - -void pdp_packet_replace_with_writable(int *packet) /* replaces a packet with a writable copy */ -{ - int new_p; - if (!pdp_packet_writable(*packet)){ - new_p = pdp_packet_copy_rw(*packet); - pdp_packet_mark_unused(*packet); - *packet = new_p; - } - -} - -/* pool stuff */ - -int -pdp_pool_collect_garbage(void) -{ - pdp_post("ERROR: garbage collector not implemented"); - return 0; -} - -void -pdp_pool_set_max_mem_usage(int max) -{ - pdp_post("ERROR: mem limit not implemented"); -} - - - - - - -#ifdef __cplusplus -} -#endif -- cgit v1.2.1