aboutsummaryrefslogtreecommitdiff
path: root/system/kernel/pdp_packet2.c
diff options
context:
space:
mode:
Diffstat (limited to 'system/kernel/pdp_packet2.c')
-rw-r--r--system/kernel/pdp_packet2.c623
1 files changed, 0 insertions, 623 deletions
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 <pdp@zzz.kotnet.org>
- *
- * 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 <stdio.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <string.h>
-#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