A stripped down to the bare minimum app_server, so that we no longer need
to compile our libbe.so with RUN_WIHTOUT_APP_SERVER for the image. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12190 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
79757df990
commit
a350a0f58e
@ -1,3 +1,4 @@
|
||||
SubDir OBOS_TOP src tests apps ;
|
||||
|
||||
SubInclude OBOS_TOP src tests apps miniterminal ;
|
||||
SubInclude OBOS_TOP src tests apps fake_app_server ;
|
||||
|
358
src/tests/apps/fake_app_server/AppServer.cpp
Normal file
358
src/tests/apps/fake_app_server/AppServer.cpp
Normal file
@ -0,0 +1,358 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2005, Haiku, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: AppServer.cpp
|
||||
// Author: DarkWyrm <bpmagic@columbus.rr.com>
|
||||
// Description: main manager object for the app_server
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
#include <AppDefs.h>
|
||||
#include <Accelerant.h>
|
||||
#include <Entry.h>
|
||||
#include <Path.h>
|
||||
#include <Directory.h>
|
||||
#include <PortLink.h>
|
||||
|
||||
#include <File.h>
|
||||
#include <Message.h>
|
||||
#include "AppServer.h"
|
||||
#include "ServerProtocol.h"
|
||||
#include "ServerApp.h"
|
||||
#include <TokenSpace.h>
|
||||
#if 0
|
||||
#include "ColorSet.h"
|
||||
#include "DisplayDriver.h"
|
||||
#include "ServerCursor.h"
|
||||
#include "ServerWindow.h"
|
||||
#include "DefaultDecorator.h"
|
||||
#include "RGBColor.h"
|
||||
#include "BitmapManager.h"
|
||||
#include "CursorManager.h"
|
||||
#include "Utils.h"
|
||||
#include "FontServer.h"
|
||||
#include "Desktop.h"
|
||||
#include "RootLayer.h"
|
||||
#endif
|
||||
#include <StopWatch.h>
|
||||
|
||||
#ifdef DEBUG_KEYHANDLING
|
||||
# include <stdio.h>
|
||||
# define KBTRACE(x) printf x
|
||||
#else
|
||||
# define KBTRACE(x) ;
|
||||
#endif
|
||||
|
||||
//#define DEBUG_SERVER
|
||||
#ifdef DEBUG_SERVER
|
||||
# define DEBUG 1
|
||||
# include <Debug.h>
|
||||
# define STRACE(x) _sPrintf x
|
||||
#else
|
||||
# define STRACE(x) ;
|
||||
#endif
|
||||
|
||||
// Globals
|
||||
|
||||
AppServer::AppServer(void)
|
||||
{
|
||||
fMessagePort = create_port(200, SERVER_PORT_NAME);
|
||||
|
||||
fAppList = new BList(0);
|
||||
fQuittingServer= false;
|
||||
|
||||
// This is necessary to mediate access between the Poller and app_server threads
|
||||
fActiveAppLock= create_sem(1,"app_server_active_sem");
|
||||
|
||||
// This locker is for app_server and Picasso to vy for control of the ServerApp list
|
||||
fAppListLock= create_sem(1,"app_server_applist_sem");
|
||||
|
||||
// Spawn our thread-monitoring thread
|
||||
fPicassoThreadID= spawn_thread(PicassoThread,"picasso", B_NORMAL_PRIORITY, this);
|
||||
if (fPicassoThreadID >= 0)
|
||||
resume_thread(fPicassoThreadID);
|
||||
}
|
||||
|
||||
|
||||
AppServer::~AppServer(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
AppServer::PicassoThread(void *data)
|
||||
{
|
||||
int32 i;
|
||||
AppServer *appserver=(AppServer*)data;
|
||||
ServerApp *app;
|
||||
for(;;)
|
||||
{
|
||||
i = 0;
|
||||
#if 1
|
||||
acquire_sem(appserver->fAppListLock);
|
||||
for(;;)
|
||||
{
|
||||
app=(ServerApp*)appserver->fAppList->ItemAt(i++);
|
||||
if(!app)
|
||||
break;
|
||||
|
||||
app->PingTarget();
|
||||
}
|
||||
release_sem(appserver->fAppListLock);
|
||||
#endif
|
||||
// we do this every other second so as not to suck *too* many CPU cycles
|
||||
snooze(1000000);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
thread_id
|
||||
AppServer::Run(void)
|
||||
{
|
||||
MainLoop();
|
||||
kill_thread(fPicassoThreadID);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//! Main message-monitoring loop for the regular message port - no input messages!
|
||||
void
|
||||
AppServer::MainLoop(void)
|
||||
{
|
||||
BPortLink pmsg(-1,fMessagePort);
|
||||
int32 code=0;
|
||||
status_t err=B_OK;
|
||||
|
||||
while(1)
|
||||
{
|
||||
STRACE(("info: AppServer::MainLoop listening on port %ld.\n", fMessagePort));
|
||||
err=pmsg.GetNextReply(&code);
|
||||
|
||||
if(err<B_OK)
|
||||
{
|
||||
STRACE(("MainLoop:pmsg.GetNextReply failed\n"));
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(code)
|
||||
{
|
||||
case B_QUIT_REQUESTED:
|
||||
case AS_CREATE_APP:
|
||||
case AS_DELETE_APP:
|
||||
case AS_GET_SCREEN_MODE:
|
||||
case AS_UPDATED_CLIENT_FONTLIST:
|
||||
case AS_QUERY_FONTS_CHANGED:
|
||||
case AS_SET_UI_COLORS:
|
||||
case AS_GET_UI_COLOR:
|
||||
case AS_SET_DECORATOR:
|
||||
case AS_GET_DECORATOR:
|
||||
case AS_R5_SET_DECORATOR:
|
||||
DispatchMessage(code,pmsg);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
STRACE(("Server::MainLoop received unexpected code %ld(offset %ld)\n",
|
||||
code,code-SERVER_TRUE));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AppServer::DispatchMessage(int32 code, BPortLink &msg)
|
||||
{
|
||||
switch(code)
|
||||
{
|
||||
#if 1
|
||||
case AS_CREATE_APP:
|
||||
{
|
||||
// Create the ServerApp to node monitor a new BApplication
|
||||
|
||||
// Attached data:
|
||||
// 1) port_id - receiver port of a regular app
|
||||
// 2) port_id - client looper port - for send messages to the client
|
||||
// 2) team_id - app's team ID
|
||||
// 3) int32 - handler token of the regular app
|
||||
// 4) char * - signature of the regular app
|
||||
|
||||
// Find the necessary data
|
||||
team_id clientTeamID=-1;
|
||||
port_id clientLooperPort=-1;
|
||||
port_id app_port=-1;
|
||||
int32 htoken=B_NULL_TOKEN;
|
||||
char *app_signature=NULL;
|
||||
|
||||
msg.Read<port_id>(&app_port);
|
||||
msg.Read<port_id>(&clientLooperPort);
|
||||
msg.Read<team_id>(&clientTeamID);
|
||||
msg.Read<int32>(&htoken);
|
||||
msg.ReadString(&app_signature);
|
||||
|
||||
// Create the ServerApp subthread for this app
|
||||
acquire_sem(fAppListLock);
|
||||
|
||||
port_id server_listen=create_port(DEFAULT_MONITOR_PORT_SIZE, app_signature);
|
||||
if(server_listen<B_OK)
|
||||
{
|
||||
release_sem(fAppListLock);
|
||||
printf("No more ports left. Time to crash. Have a nice day! :)\n");
|
||||
break;
|
||||
}
|
||||
ServerApp *newapp=NULL;
|
||||
newapp= new ServerApp(app_port,server_listen, clientLooperPort, clientTeamID,
|
||||
htoken, app_signature);
|
||||
|
||||
// add the new ServerApp to the known list of ServerApps
|
||||
fAppList->AddItem(newapp);
|
||||
|
||||
release_sem(fAppListLock);
|
||||
|
||||
BPortLink replylink(app_port);
|
||||
replylink.StartMessage(SERVER_TRUE);
|
||||
replylink.Attach<int32>(newapp->fMessagePort);
|
||||
replylink.Flush();
|
||||
|
||||
// This is necessary because BPortLink::ReadString allocates memory
|
||||
if(app_signature)
|
||||
free(app_signature);
|
||||
|
||||
break;
|
||||
}
|
||||
case AS_DELETE_APP:
|
||||
{
|
||||
// Delete a ServerApp. Received only from the respective ServerApp when a
|
||||
// BApplication asks it to quit.
|
||||
|
||||
// Attached Data:
|
||||
// 1) thread_id - thread ID of the ServerApp to be deleted
|
||||
|
||||
int32 i=0,
|
||||
appnum=fAppList->CountItems();
|
||||
|
||||
ServerApp *srvapp=NULL;
|
||||
thread_id srvapp_id=-1;
|
||||
|
||||
if(msg.Read<thread_id>(&srvapp_id)<B_OK)
|
||||
break;
|
||||
|
||||
acquire_sem(fAppListLock);
|
||||
|
||||
// Run through the list of apps and nuke the proper one
|
||||
for(i= 0; i < appnum; i++)
|
||||
{
|
||||
srvapp=(ServerApp *)fAppList->ItemAt(i);
|
||||
|
||||
if(srvapp != NULL && srvapp->fMonitorThreadID== srvapp_id)
|
||||
{
|
||||
srvapp=(ServerApp *)fAppList->RemoveItem(i);
|
||||
if(srvapp)
|
||||
{
|
||||
status_t temp;
|
||||
wait_for_thread(srvapp_id, &temp);
|
||||
delete srvapp;
|
||||
srvapp= NULL;
|
||||
}
|
||||
break; // jump out of our for() loop
|
||||
}
|
||||
}
|
||||
|
||||
release_sem(fAppListLock);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case AS_QUERY_FONTS_CHANGED:
|
||||
{
|
||||
// Seeing how the client merely wants an answer, we'll skip the BPortLink
|
||||
// and all its overhead and just write the code to port.
|
||||
port_id replyport;
|
||||
if (msg.Read<port_id>(&replyport) < B_OK)
|
||||
break;
|
||||
BPortLink replylink(replyport);
|
||||
replylink.StartMessage(SERVER_FALSE);
|
||||
replylink.Flush();
|
||||
break;
|
||||
}
|
||||
case AS_GET_DECORATOR:
|
||||
{
|
||||
// Attached Data:
|
||||
// 1) port_id reply port
|
||||
|
||||
port_id replyport=-1;
|
||||
if(msg.Read<port_id>(&replyport)<B_OK)
|
||||
return;
|
||||
|
||||
BPortLink replylink(replyport);
|
||||
replylink.StartMessage(AS_GET_DECORATOR);
|
||||
replylink.AttachString("none");
|
||||
replylink.Flush();
|
||||
break;
|
||||
}
|
||||
case AS_GET_SCREEN_MODE:
|
||||
{
|
||||
// Synchronous message call to get the stats on the current screen mode
|
||||
// in the app_server. Simply a hack in place for the Input Server until
|
||||
// BScreens are done.
|
||||
|
||||
// Attached Data:
|
||||
// 1) port_id - port to reply to
|
||||
|
||||
// Returned Data:
|
||||
// 1) int32 width
|
||||
// 2) int32 height
|
||||
// 3) int depth
|
||||
|
||||
display_mode dmode;
|
||||
|
||||
port_id replyport=-1;
|
||||
if(msg.Read<port_id>(&replyport)<B_OK)
|
||||
break;
|
||||
|
||||
BPortLink replylink(replyport);
|
||||
replylink.StartMessage(AS_GET_SCREEN_MODE);
|
||||
replylink.Attach<display_mode>(dmode);
|
||||
replylink.Flush();
|
||||
break;
|
||||
}
|
||||
|
||||
case AS_UPDATED_CLIENT_FONTLIST:
|
||||
case AS_SET_UI_COLORS:
|
||||
case AS_SET_DECORATOR:
|
||||
case AS_R5_SET_DECORATOR:
|
||||
case AS_SET_SYSCURSOR_DEFAULTS:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
// There can be only one....
|
||||
if (find_port(SERVER_PORT_NAME) != B_NAME_NOT_FOUND)
|
||||
return -1;
|
||||
|
||||
AppServer app_server;
|
||||
app_server.Run();
|
||||
return 0;
|
||||
}
|
46
src/tests/apps/fake_app_server/AppServer.h
Normal file
46
src/tests/apps/fake_app_server/AppServer.h
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef _OPENBEOS_APP_SERVER_H_
|
||||
#define _OPENBEOS_APP_SERVER_H_
|
||||
|
||||
#include <OS.h>
|
||||
#include <Locker.h>
|
||||
#include <List.h>
|
||||
#include <Application.h>
|
||||
#include <Window.h>
|
||||
#include <String.h>
|
||||
#include "Decorator.h"
|
||||
#include "ServerConfig.h"
|
||||
|
||||
class Layer;
|
||||
class BMessage;
|
||||
class ServerApp;
|
||||
class DisplayDriver;
|
||||
class BPortLink;
|
||||
class CursorManager;
|
||||
class BitmapManager;
|
||||
|
||||
class AppServer
|
||||
{
|
||||
public:
|
||||
AppServer(void);
|
||||
~AppServer(void);
|
||||
|
||||
static int32 PollerThread(void *data);
|
||||
static int32 PicassoThread(void *data);
|
||||
thread_id Run(void);
|
||||
void MainLoop(void);
|
||||
|
||||
void DispatchMessage(int32 code, BPortLink &link);
|
||||
|
||||
private:
|
||||
port_id fMessagePort;
|
||||
bool fQuittingServer;
|
||||
|
||||
BList *fAppList;
|
||||
thread_id fPicassoThreadID;
|
||||
|
||||
sem_id fActiveAppLock, fAppListLock;
|
||||
};
|
||||
|
||||
extern AppServer *app_server;
|
||||
|
||||
#endif
|
854
src/tests/apps/fake_app_server/BGet++.cpp
Normal file
854
src/tests/apps/fake_app_server/BGet++.cpp
Normal file
@ -0,0 +1,854 @@
|
||||
/*------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2002, Haiku, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: bget++.cpp
|
||||
// Author: John Walker <kelvin@fourmilab.ch>
|
||||
// DarkWyrm <bpmagic@columbus.rr.com>
|
||||
// Description: public domain BGET pool allocator converted to C++
|
||||
// Distributed with Haiku under MIT license
|
||||
//
|
||||
//------------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
This class is based on the BGET pool allocator. Original code was in standard
|
||||
ANSI C with a bunch of static variables. The original code was placed into the
|
||||
MemPool class and the original allocation, release, and compacting functions
|
||||
were made into virtual members. MemPool also, unlike the original code, makes
|
||||
use of malloc() and free() to handle dynamic memory needs. AreaPool is a MemPool
|
||||
subclass which uses areas to handle memory management needs in large chunks.
|
||||
*/
|
||||
|
||||
|
||||
// Buffer allocation size quantum: all buffers allocated are a multiple of this size. '
|
||||
// This MUST be a power of two.
|
||||
#define SizeQuant 4
|
||||
|
||||
#include <stdio.h>
|
||||
#include <OS.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
// Declare the interface, including the requested buffer size type, ssize_t.
|
||||
#include "BGet++.h"
|
||||
|
||||
// Queue links
|
||||
struct qlinks
|
||||
{
|
||||
struct bfhead *flink; // Forward link
|
||||
struct bfhead *blink; // Backward link
|
||||
};
|
||||
|
||||
// Header in allocated and free buffers
|
||||
struct bhead
|
||||
{
|
||||
// Relative link back to previous free buffer in memory or 0 if previous
|
||||
// buffer is allocated.
|
||||
ssize_t prevfree;
|
||||
|
||||
// Buffer size: positive if free, negative if allocated.
|
||||
ssize_t bsize;
|
||||
};
|
||||
|
||||
#define BH(p) ((struct bhead *) (p))
|
||||
|
||||
// Header in directly allocated buffers (by acqfcn)
|
||||
struct bdhead
|
||||
{
|
||||
ssize_t tsize; // Total size, including overhead
|
||||
struct bhead bh; // Common header
|
||||
};
|
||||
|
||||
#define BDH(p) ((struct bdhead *) (p))
|
||||
|
||||
// Header in free buffers
|
||||
struct bfhead
|
||||
{
|
||||
// Common allocated/free header
|
||||
struct bhead bh;
|
||||
|
||||
// Links on free list
|
||||
struct qlinks ql;
|
||||
};
|
||||
|
||||
#define BFH(p) ((struct bfhead *) (p))
|
||||
|
||||
static struct bfhead freelist =
|
||||
{
|
||||
// List of free buffers
|
||||
{0, 0},
|
||||
{&freelist, &freelist}
|
||||
};
|
||||
|
||||
|
||||
// Minimum allocation quantum:
|
||||
#define QLSize (sizeof(struct qlinks))
|
||||
#define SizeQ ((SizeQuant > QLSize) ? SizeQuant : QLSize)
|
||||
|
||||
// End sentinel: value placed in bsize field of dummy block delimiting end of
|
||||
// pool block. The most negative number which will fit in a ssize_t,
|
||||
// defined in a way that the compiler will accept.
|
||||
#define ESent ((ssize_t) (-(((1L << (sizeof(ssize_t) * 8 - 2)) - 1) * 2) - 2))
|
||||
|
||||
|
||||
MemPool::MemPool(void)
|
||||
: totalloc(0),
|
||||
numget(0),
|
||||
numrel(0),
|
||||
numpblk(0),
|
||||
numpget(0),
|
||||
numprel(0),
|
||||
numdget(0),
|
||||
numdrel(0),
|
||||
exp_incr(0),
|
||||
pool_len(0)
|
||||
{
|
||||
}
|
||||
|
||||
MemPool::~MemPool(void)
|
||||
{
|
||||
}
|
||||
|
||||
// Allocate a buffer from the available space in the memory pool
|
||||
void *MemPool::GetBuffer(ssize_t requested_size, bool zero)
|
||||
{
|
||||
ssize_t size = requested_size;
|
||||
struct bfhead *b;
|
||||
|
||||
struct bfhead *best;
|
||||
void *buf;
|
||||
|
||||
int compactseq = 0;
|
||||
|
||||
assert(size > 0);
|
||||
|
||||
if (size < (ssize_t)SizeQ)
|
||||
{
|
||||
// Need at least room for the queue links.
|
||||
size = SizeQ;
|
||||
}
|
||||
|
||||
#if SizeQuant > 1
|
||||
size = (size + (SizeQuant - 1)) & (~(SizeQuant - 1));
|
||||
#endif
|
||||
|
||||
// Add overhead in allocated buffer to size required.
|
||||
size += sizeof(struct bhead);
|
||||
|
||||
// If a compact function was provided in the call to bectl(), wrap
|
||||
// a loop around the allocation process to allow compaction to
|
||||
// intervene in case we don't find a suitable buffer in the chain.
|
||||
while (1)
|
||||
{
|
||||
b = freelist.ql.flink;
|
||||
best = &freelist;
|
||||
|
||||
|
||||
// Scan the free list searching for the first buffer big enough
|
||||
// to hold the requested size buffer.
|
||||
|
||||
while (b != &freelist)
|
||||
{
|
||||
if (b->bh.bsize >= size)
|
||||
{
|
||||
if ((best == &freelist) || (b->bh.bsize < best->bh.bsize))
|
||||
{
|
||||
best = b;
|
||||
}
|
||||
}
|
||||
|
||||
b = b->ql.flink; // Link to next buffer
|
||||
}
|
||||
b = best;
|
||||
|
||||
while (b != &freelist)
|
||||
{
|
||||
if ((ssize_t) b->bh.bsize >= size)
|
||||
{
|
||||
|
||||
// Buffer is big enough to satisfy the request. Allocate it to the caller.
|
||||
// We must decide whether the buffer is large enough to split into the part
|
||||
// given to the caller and a free buffer that remains on the free list, or
|
||||
// whether the entire buffer should be removed from the free list and given
|
||||
// to the caller in its entirety. We only split the buffer if enough room
|
||||
// remains for a header plus the minimum quantum of allocation.
|
||||
|
||||
if ((b->bh.bsize - size) > (ssize_t)(SizeQ + (sizeof(struct bhead))))
|
||||
{
|
||||
struct bhead *ba, *bn;
|
||||
|
||||
ba = BH(((char *) b) + (b->bh.bsize - size));
|
||||
bn = BH(((char *) ba) + size);
|
||||
assert(bn->prevfree == b->bh.bsize);
|
||||
|
||||
// Subtract size from length of free block.
|
||||
b->bh.bsize -= size;
|
||||
|
||||
// Link allocated buffer to the previous free buffer.
|
||||
ba->prevfree = b->bh.bsize;
|
||||
|
||||
// Plug negative size into user buffer.
|
||||
ba->bsize = -(ssize_t) size;
|
||||
|
||||
// Mark buffer after this one not preceded by free block.
|
||||
bn->prevfree = 0;
|
||||
|
||||
totalloc += size;
|
||||
numget++; // Increment number of GetBuffer() calls
|
||||
|
||||
buf = (void *) ((((char *) ba) + sizeof(struct bhead)));
|
||||
return buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct bhead *ba;
|
||||
|
||||
ba = BH(((char *) b) + b->bh.bsize);
|
||||
assert(ba->prevfree == b->bh.bsize);
|
||||
|
||||
// The buffer isn't big enough to split. Give the whole
|
||||
// shebang to the caller and remove it from the free list.
|
||||
|
||||
assert(b->ql.blink->ql.flink == b);
|
||||
assert(b->ql.flink->ql.blink == b);
|
||||
b->ql.blink->ql.flink = b->ql.flink;
|
||||
b->ql.flink->ql.blink = b->ql.blink;
|
||||
|
||||
totalloc += b->bh.bsize;
|
||||
numget++; // Increment number of GetBuffer() calls
|
||||
|
||||
// Negate size to mark buffer allocated.
|
||||
b->bh.bsize = -(b->bh.bsize);
|
||||
|
||||
// Zero the back pointer in the next buffer in memory
|
||||
// to indicate that this buffer is allocated.
|
||||
ba->prevfree = 0;
|
||||
|
||||
// Give user buffer starting at queue links.
|
||||
buf = (void *) &(b->ql);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
b = b->ql.flink; // Link to next buffer
|
||||
}
|
||||
|
||||
|
||||
// We failed to find a buffer. If there's a compact function
|
||||
// defined, notify it of the size requested. If it returns
|
||||
// TRUE, try the allocation again.
|
||||
|
||||
if(!CompactMem(size, ++compactseq))
|
||||
break;
|
||||
}
|
||||
|
||||
// No buffer available with requested size free.
|
||||
|
||||
// Don't give up yet -- look in the reserve supply.
|
||||
if (size > (ssize_t)(exp_incr - sizeof(struct bhead)))
|
||||
{
|
||||
// Request is too large to fit in a single expansion
|
||||
// block. Try to satisy it by a direct buffer acquisition.
|
||||
struct bdhead *bdh;
|
||||
|
||||
size += sizeof(struct bdhead) - sizeof(struct bhead);
|
||||
if ((bdh = BDH(AcquireMem((ssize_t) size))) != NULL)
|
||||
{
|
||||
// Mark the buffer special by setting the size field
|
||||
// of its header to zero.
|
||||
bdh->bh.bsize = 0;
|
||||
bdh->bh.prevfree = 0;
|
||||
bdh->tsize = size;
|
||||
|
||||
totalloc += size;
|
||||
|
||||
// Increment number of GetBuffer() calls
|
||||
numget++;
|
||||
|
||||
// Direct GetBuffer() call count
|
||||
numdget++;
|
||||
|
||||
buf = (void *) (bdh + 1);
|
||||
return buf;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Try to obtain a new expansion block
|
||||
void *newpool;
|
||||
|
||||
if ((newpool = AcquireMem((ssize_t) exp_incr)) != NULL)
|
||||
{
|
||||
AddToPool(newpool, exp_incr);
|
||||
|
||||
// This can't, I say, can't get into a loop
|
||||
buf = GetBuffer(requested_size);
|
||||
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
// Still no buffer available
|
||||
return NULL;
|
||||
|
||||
// Code from bgetz -- zeroing code
|
||||
/*
|
||||
char *buf = (char *) GetBuffer(size);
|
||||
|
||||
if (buf != NULL)
|
||||
{
|
||||
struct bhead *b;
|
||||
ssize_t rsize;
|
||||
|
||||
b = BH(buf - sizeof(struct bhead));
|
||||
rsize = -(b->bsize);
|
||||
|
||||
if (rsize == 0)
|
||||
{
|
||||
struct bdhead *bd;
|
||||
|
||||
bd = BDH(buf - sizeof(struct bdhead));
|
||||
rsize = bd->tsize - sizeof(struct bdhead);
|
||||
}
|
||||
else
|
||||
{
|
||||
rsize -= sizeof(struct bhead);
|
||||
}
|
||||
|
||||
assert(rsize >= size);
|
||||
memset(buf, 0, (MemSize) rsize);
|
||||
}
|
||||
return ((void *) buf);
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
// Reallocate a buffer. This is a minimal implementation, simply in terms
|
||||
// of ReleaseBuffer() and GetBuffer(). It could be enhanced to allow the
|
||||
// buffer to grow into adjacent free blocks and to avoid moving data unnecessarily.
|
||||
void *MemPool::ReallocateBuffer(void *buf, ssize_t size)
|
||||
{
|
||||
void *nbuf;
|
||||
|
||||
// Old size of buffer
|
||||
ssize_t osize;
|
||||
struct bhead *b;
|
||||
|
||||
if ((nbuf = GetBuffer(size)) == NULL)
|
||||
{
|
||||
// Acquire new buffer
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (buf == NULL)
|
||||
{
|
||||
return nbuf;
|
||||
}
|
||||
b = BH(((char *) buf) - sizeof(struct bhead));
|
||||
osize = -b->bsize;
|
||||
|
||||
if (osize == 0)
|
||||
{
|
||||
// Buffer acquired directly through acqfcn.
|
||||
struct bdhead *bd;
|
||||
|
||||
bd = BDH(((char *) buf) - sizeof(struct bdhead));
|
||||
osize = bd->tsize - sizeof(struct bdhead);
|
||||
}
|
||||
else
|
||||
osize -= sizeof(struct bhead);
|
||||
assert(osize > 0);
|
||||
|
||||
// Copy the data
|
||||
memcpy((char *) nbuf, (char *) buf, (int) ((size < osize) ? size : osize));
|
||||
ReleaseBuffer(buf);
|
||||
return nbuf;
|
||||
}
|
||||
|
||||
// BREL -- Release a buffer.
|
||||
void MemPool::ReleaseBuffer(void *buf)
|
||||
{
|
||||
struct bfhead *b, *bn;
|
||||
|
||||
b = BFH(((char *) buf) - sizeof(struct bhead));
|
||||
|
||||
// Increment number of ReleaseBuffer() calls
|
||||
numrel++;
|
||||
|
||||
assert(buf != NULL);
|
||||
|
||||
// Directly-acquired buffer?
|
||||
if (b->bh.bsize == 0)
|
||||
{
|
||||
struct bdhead *bdh;
|
||||
|
||||
bdh = BDH(((char *) buf) - sizeof(struct bdhead));
|
||||
assert(b->bh.prevfree == 0);
|
||||
|
||||
totalloc -= bdh->tsize;
|
||||
assert(totalloc >= 0);
|
||||
|
||||
// Number of direct releases
|
||||
numdrel++;
|
||||
|
||||
memset((char *) buf, 0x55, (int) (bdh->tsize - sizeof(struct bdhead)));
|
||||
|
||||
// Release it directly.
|
||||
ReleaseMem((void *) bdh);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Buffer size must be negative, indicating that the buffer is allocated.
|
||||
if (b->bh.bsize >= 0)
|
||||
{
|
||||
bn = NULL;
|
||||
}
|
||||
assert(b->bh.bsize < 0);
|
||||
|
||||
// Back pointer in next buffer must be zero, indicating the same thing:
|
||||
assert(BH((char *) b - b->bh.bsize)->prevfree == 0);
|
||||
|
||||
totalloc += b->bh.bsize;
|
||||
assert(totalloc >= 0);
|
||||
|
||||
|
||||
// If the back link is nonzero, the previous buffer is free.
|
||||
|
||||
if (b->bh.prevfree != 0)
|
||||
{
|
||||
// The previous buffer is free. Consolidate this buffer with it
|
||||
// by adding the length of this buffer to the previous free
|
||||
// buffer. Note that we subtract the size in the buffer being
|
||||
// released, since it's negative to indicate that the buffer is allocated.
|
||||
|
||||
register ssize_t size = b->bh.bsize;
|
||||
|
||||
// Make the previous buffer the one we're working on.
|
||||
assert(BH((char *) b - b->bh.prevfree)->bsize == b->bh.prevfree);
|
||||
b = BFH(((char *) b) - b->bh.prevfree);
|
||||
b->bh.bsize -= size;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The previous buffer isn't allocated. Insert this buffer on the
|
||||
// free list as an isolated free block.
|
||||
assert(freelist.ql.blink->ql.flink == &freelist);
|
||||
assert(freelist.ql.flink->ql.blink == &freelist);
|
||||
b->ql.flink = &freelist;
|
||||
b->ql.blink = freelist.ql.blink;
|
||||
freelist.ql.blink = b;
|
||||
b->ql.blink->ql.flink = b;
|
||||
b->bh.bsize = -b->bh.bsize;
|
||||
}
|
||||
|
||||
// Now we look at the next buffer in memory, located by advancing from
|
||||
// the start of this buffer by its size, to see if that buffer is
|
||||
// free. If it is, we combine this buffer with the next one in
|
||||
// memory, dechaining the second buffer from the free list.
|
||||
|
||||
bn = BFH(((char *) b) + b->bh.bsize);
|
||||
if (bn->bh.bsize > 0)
|
||||
{
|
||||
// The buffer is free. Remove it from the free list and add
|
||||
// its size to that of our buffer.
|
||||
assert(BH((char *) bn + bn->bh.bsize)->prevfree == bn->bh.bsize);
|
||||
assert(bn->ql.blink->ql.flink == bn);
|
||||
assert(bn->ql.flink->ql.blink == bn);
|
||||
bn->ql.blink->ql.flink = bn->ql.flink;
|
||||
bn->ql.flink->ql.blink = bn->ql.blink;
|
||||
b->bh.bsize += bn->bh.bsize;
|
||||
|
||||
// Finally, advance to the buffer that follows the newly
|
||||
// consolidated free block. We must set its backpointer to the
|
||||
// head of the consolidated free block. We know the next block
|
||||
// must be an allocated block because the process of recombination
|
||||
// guarantees that two free blocks will never be contiguous in
|
||||
// memory.
|
||||
bn = BFH(((char *) b) + b->bh.bsize);
|
||||
}
|
||||
|
||||
memset(((char *) b) + sizeof(struct bfhead), 0x55,(int) (b->bh.bsize - sizeof(struct bfhead)));
|
||||
|
||||
assert(bn->bh.bsize < 0);
|
||||
|
||||
// The next buffer is allocated. Set the backpointer in it to point
|
||||
// to this buffer; the previous free buffer in memory.
|
||||
bn->bh.prevfree = b->bh.bsize;
|
||||
|
||||
// If a block-release function is defined, and this free buffer
|
||||
// constitutes the entire block, release it. Note that pool_len
|
||||
// is defined in such a way that the test will fail unless all
|
||||
// pool blocks are the same size.
|
||||
|
||||
if (((ssize_t) b->bh.bsize) == (ssize_t)(pool_len - sizeof(struct bhead)))
|
||||
{
|
||||
assert(b->bh.prevfree == 0);
|
||||
assert(BH((char *) b + b->bh.bsize)->bsize == ESent);
|
||||
assert(BH((char *) b + b->bh.bsize)->prevfree == b->bh.bsize);
|
||||
|
||||
// Unlink the buffer from the free list
|
||||
b->ql.blink->ql.flink = b->ql.flink;
|
||||
b->ql.flink->ql.blink = b->ql.blink;
|
||||
|
||||
ReleaseMem(b);
|
||||
|
||||
// Nr of expansion block releases
|
||||
numprel++;
|
||||
|
||||
// Total number of blocks
|
||||
numpblk--;
|
||||
assert(numpblk == numpget - numprel);
|
||||
}
|
||||
}
|
||||
|
||||
// Add a region of memory to the buffer pool.
|
||||
void MemPool::AddToPool(void *buf, ssize_t len)
|
||||
{
|
||||
struct bfhead *b = BFH(buf);
|
||||
struct bhead *bn;
|
||||
|
||||
len &= ~(SizeQuant - 1);
|
||||
|
||||
if (pool_len == 0)
|
||||
{
|
||||
pool_len = len;
|
||||
}
|
||||
else
|
||||
if (len != pool_len)
|
||||
{
|
||||
pool_len = -1;
|
||||
}
|
||||
|
||||
// Number of block acquisitions
|
||||
numpget++;
|
||||
|
||||
// Number of blocks total
|
||||
numpblk++;
|
||||
assert(numpblk == numpget - numprel);
|
||||
|
||||
// Since the block is initially occupied by a single free buffer,
|
||||
// it had better not be (much) larger than the largest buffer
|
||||
// whose size we can store in bhead.bsize.
|
||||
assert(len - sizeof(struct bhead) <= -((ssize_t) ESent + 1));
|
||||
|
||||
// Clear the backpointer at the start of the block to indicate that
|
||||
// there is no free block prior to this one. That blocks
|
||||
// recombination when the first block in memory is released.
|
||||
b->bh.prevfree = 0;
|
||||
|
||||
// Chain the new block to the free list.
|
||||
assert(freelist.ql.blink->ql.flink == &freelist);
|
||||
assert(freelist.ql.flink->ql.blink == &freelist);
|
||||
b->ql.flink = &freelist;
|
||||
b->ql.blink = freelist.ql.blink;
|
||||
freelist.ql.blink = b;
|
||||
b->ql.blink->ql.flink = b;
|
||||
|
||||
// Create a dummy allocated buffer at the end of the pool. This dummy
|
||||
// buffer is seen when a buffer at the end of the pool is released and
|
||||
// blocks recombination of the last buffer with the dummy buffer at
|
||||
// the end. The length in the dummy buffer is set to the largest
|
||||
// negative number to denote the end of the pool for diagnostic
|
||||
// routines (this specific value is not counted on by the actual
|
||||
// allocation and release functions).
|
||||
|
||||
len -= sizeof(struct bhead);
|
||||
b->bh.bsize = (ssize_t) len;
|
||||
|
||||
memset(((char *) b) + sizeof(struct bfhead), 0x55,(int) (len - sizeof(struct bfhead)));
|
||||
|
||||
bn = BH(((char *) b) + len);
|
||||
bn->prevfree = (ssize_t) len;
|
||||
|
||||
// Definition of ESent assumes two's complement!
|
||||
assert((~0) == -1);
|
||||
bn->bsize = ESent;
|
||||
}
|
||||
|
||||
|
||||
// Return buffer allocation free space statistics.
|
||||
void MemPool::Stats(ssize_t *curalloc, ssize_t *totfree, ssize_t *maxfree,
|
||||
long *nget, long *nrel)
|
||||
{
|
||||
struct bfhead *b = freelist.ql.flink;
|
||||
|
||||
*nget = numget;
|
||||
*nrel = numrel;
|
||||
*curalloc = totalloc;
|
||||
*totfree = 0;
|
||||
*maxfree = -1;
|
||||
while (b != &freelist)
|
||||
{
|
||||
assert(b->bh.bsize > 0);
|
||||
*totfree += b->bh.bsize;
|
||||
if (b->bh.bsize > *maxfree)
|
||||
{
|
||||
*maxfree = b->bh.bsize;
|
||||
}
|
||||
|
||||
// Link to next buffer
|
||||
b = b->ql.flink;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Return extended statistics
|
||||
void MemPool::ExtendedStats(ssize_t *pool_incr, long *npool, long *npget, long *nprel,
|
||||
long *ndget, long *ndrel)
|
||||
{
|
||||
*pool_incr = (pool_len < 0) ? -exp_incr : exp_incr;
|
||||
*npool = numpblk;
|
||||
*npget = numpget;
|
||||
*nprel = numprel;
|
||||
*ndget = numdget;
|
||||
*ndrel = numdrel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Dump the data in a buffer. This is called with the user data pointer,
|
||||
// and backs up to the buffer header. It will dump either a free block
|
||||
// or an allocated one.
|
||||
void MemPool::BufferDump(void *buf)
|
||||
{
|
||||
struct bfhead *b;
|
||||
unsigned char *bdump;
|
||||
ssize_t bdlen;
|
||||
|
||||
b = BFH(((char *) buf) - sizeof(struct bhead));
|
||||
assert(b->bh.bsize != 0);
|
||||
if (b->bh.bsize < 0)
|
||||
{
|
||||
bdump = (unsigned char *) buf;
|
||||
bdlen = (-b->bh.bsize) - sizeof(struct bhead);
|
||||
}
|
||||
else
|
||||
{
|
||||
bdump = (unsigned char *) (((char *) b) + sizeof(struct bfhead));
|
||||
bdlen = b->bh.bsize - sizeof(struct bfhead);
|
||||
}
|
||||
|
||||
while (bdlen > 0)
|
||||
{
|
||||
int i, dupes = 0;
|
||||
ssize_t l = bdlen;
|
||||
char bhex[50], bascii[20];
|
||||
|
||||
if (l > 16)
|
||||
{
|
||||
l = 16;
|
||||
}
|
||||
|
||||
for (i = 0; i < l; i++)
|
||||
{
|
||||
sprintf(bhex + i * 3, "%02X ", bdump[i]);
|
||||
bascii[i] = isprint(bdump[i]) ? bdump[i] : ' ';
|
||||
}
|
||||
bascii[i] = 0;
|
||||
printf("%-48s %s\n", bhex, bascii);
|
||||
bdump += l;
|
||||
bdlen -= l;
|
||||
while ((bdlen > 16) && (memcmp((char *) (bdump - 16),(char *) bdump, 16) == 0))
|
||||
{
|
||||
dupes++;
|
||||
bdump += 16;
|
||||
bdlen -= 16;
|
||||
}
|
||||
|
||||
if (dupes > 1)
|
||||
{
|
||||
printf(" (%d lines [%d bytes] identical to above line skipped)\n",
|
||||
dupes, dupes * 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dupes == 1)
|
||||
{
|
||||
bdump -= 16;
|
||||
bdlen += 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dump a buffer pool. The buffer headers are always listed. If DUMPALLOC is
|
||||
// nonzero, the contents of allocated buffers are dumped. If DUMPFREE is
|
||||
// nonzero, free blocks are dumped as well. If FreeWipe checking is enabled,
|
||||
// free blocks which have been clobbered will always be dumped.
|
||||
void MemPool::PoolDump(void *buf, bool dumpalloc, bool dumpfree)
|
||||
{
|
||||
struct bfhead *b = BFH(buf);
|
||||
|
||||
while (b->bh.bsize != ESent)
|
||||
{
|
||||
ssize_t bs = b->bh.bsize;
|
||||
|
||||
if (bs < 0)
|
||||
{
|
||||
bs = -bs;
|
||||
printf("Allocated buffer: size %6ld bytes.\n", (long) bs);
|
||||
if (dumpalloc)
|
||||
{
|
||||
BufferDump((void *) (((char *) b) + sizeof(struct bhead)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char *lerr = "";
|
||||
|
||||
assert(bs > 0);
|
||||
if ((b->ql.blink->ql.flink != b) || (b->ql.flink->ql.blink != b))
|
||||
{
|
||||
lerr = " (Bad free list links)";
|
||||
}
|
||||
printf("Free block: size %6ld bytes.%s\n",
|
||||
(long) bs, lerr);
|
||||
|
||||
lerr = ((char *) b) + sizeof(struct bfhead);
|
||||
if ((bs > (ssize_t)sizeof(struct bfhead)) && ((*lerr != 0x55) ||
|
||||
(memcmp(lerr, lerr + 1, (int) (bs - (sizeof(struct bfhead) + 1))) != 0)))
|
||||
{
|
||||
printf("(Contents of above free block have been overstored.)\n");
|
||||
BufferDump((void *) (((char *) b) + sizeof(struct bhead)));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dumpfree)
|
||||
{
|
||||
BufferDump((void *) (((char *) b) + sizeof(struct bhead)));
|
||||
}
|
||||
}
|
||||
}
|
||||
b = BFH(((char *) b) + bs);
|
||||
}
|
||||
}
|
||||
|
||||
// Validate a buffer pool.
|
||||
int MemPool::Validate(void *buf)
|
||||
{
|
||||
struct bfhead *b = BFH(buf);
|
||||
|
||||
while (b->bh.bsize != ESent)
|
||||
{
|
||||
ssize_t bs = b->bh.bsize;
|
||||
|
||||
if (bs < 0)
|
||||
{
|
||||
bs = -bs;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *lerr = "";
|
||||
|
||||
assert(bs > 0);
|
||||
if (bs <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((b->ql.blink->ql.flink != b) || (b->ql.flink->ql.blink != b))
|
||||
{
|
||||
printf("Free block: size %6ld bytes. (Bad free list links)\n",
|
||||
(long) bs);
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lerr = ((char *) b) + sizeof(struct bfhead);
|
||||
if ((bs > (ssize_t)sizeof(struct bfhead)) && ((*lerr != 0x55) ||
|
||||
(memcmp(lerr, lerr + 1,(int) (bs - (sizeof(struct bfhead) + 1))) != 0)))
|
||||
{
|
||||
printf("(Contents of above free block have been overstored.)\n");
|
||||
BufferDump((void *) (((char *) b) + sizeof(struct bhead)));
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
b = BFH(((char *) b) + bs);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int *MemPool::CompactMem(ssize_t sizereq, int sequence)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *MemPool::AcquireMem(ssize_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void MemPool::ReleaseMem(void *buffer)
|
||||
{
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
AreaPool::AreaPool(void)
|
||||
{
|
||||
}
|
||||
|
||||
AreaPool::~AreaPool(void)
|
||||
{
|
||||
}
|
||||
|
||||
void *AreaPool::AcquireMem(ssize_t size)
|
||||
{
|
||||
long areasize=0;
|
||||
area_id a;
|
||||
int *parea;
|
||||
|
||||
if(size<B_PAGE_SIZE)
|
||||
areasize=B_PAGE_SIZE;
|
||||
else
|
||||
{
|
||||
if((size % B_PAGE_SIZE)!=0)
|
||||
areasize=((long)(size/B_PAGE_SIZE)+1)*B_PAGE_SIZE;
|
||||
else
|
||||
areasize=size;
|
||||
}
|
||||
|
||||
a=create_area("AreaPool_area",(void**)&parea,B_ANY_ADDRESS,areasize,
|
||||
B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
|
||||
|
||||
if(a==B_BAD_VALUE || a==B_NO_MEMORY || a==B_ERROR)
|
||||
{
|
||||
printf("ERROR: AreaPool couldn't allocate area!!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return parea;
|
||||
}
|
||||
|
||||
void AreaPool::ReleaseMem(void *buffer)
|
||||
{
|
||||
area_id trash=area_for(buffer);
|
||||
|
||||
if(trash==B_ERROR)
|
||||
return;
|
||||
|
||||
delete_area(trash);
|
||||
}
|
||||
|
53
src/tests/apps/fake_app_server/BGet++.h
Normal file
53
src/tests/apps/fake_app_server/BGet++.h
Normal file
@ -0,0 +1,53 @@
|
||||
#ifndef HGET_H_
|
||||
#define HGET_H_
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
class MemPool
|
||||
{
|
||||
public:
|
||||
MemPool(void);
|
||||
virtual ~MemPool(void);
|
||||
|
||||
void AddToPool(void *buffer, ssize_t len);
|
||||
void *GetBuffer(ssize_t size, bool zero=false);
|
||||
void *ReallocateBuffer(void *buffer, ssize_t size);
|
||||
void ReleaseBuffer(void *buffer);
|
||||
|
||||
virtual int *CompactMem(ssize_t sizereq, int sequence);
|
||||
virtual void *AcquireMem(ssize_t size);
|
||||
virtual void ReleaseMem(void *buffer);
|
||||
void SetPoolIncrement(ssize_t increment);
|
||||
ssize_t PoolIncrement(void);
|
||||
|
||||
void Stats(ssize_t *curalloc, ssize_t *totfree, ssize_t *maxfree,
|
||||
long *nget, long *nrel);
|
||||
|
||||
void ExtendedStats(ssize_t *pool_incr, long *npool, long *npget,
|
||||
long *nprel, long *ndget, long *ndrel);
|
||||
|
||||
void BufferDump(void *buf);
|
||||
void PoolDump(void *pool, bool dumpalloc, bool dumpfree);
|
||||
int Validate(void *buffer);
|
||||
|
||||
private:
|
||||
ssize_t totalloc;
|
||||
long numget, numrel;
|
||||
long numpblk;
|
||||
long numpget, numprel;
|
||||
long numdget, numdrel;
|
||||
ssize_t exp_incr;
|
||||
ssize_t pool_len;
|
||||
|
||||
};
|
||||
|
||||
class AreaPool : public MemPool
|
||||
{
|
||||
public:
|
||||
AreaPool(void);
|
||||
virtual ~AreaPool(void);
|
||||
virtual void *AcquireMem(ssize_t size);
|
||||
virtual void ReleaseMem(void *buffer);
|
||||
};
|
||||
|
||||
#endif
|
17
src/tests/apps/fake_app_server/Jamfile
Normal file
17
src/tests/apps/fake_app_server/Jamfile
Normal file
@ -0,0 +1,17 @@
|
||||
SubDir OBOS_TOP src tests apps fake_app_server ;
|
||||
|
||||
UseLibraryHeaders agg png zlib ;
|
||||
UsePrivateHeaders app interface [ FDirName servers app ] ;
|
||||
UseHeaders [ FDirName $(OBOS_TOP) src servers app drawing ] ;
|
||||
UseHeaders [ FDirName $(OBOS_TOP) src servers app drawing Painter ] ;
|
||||
UseHeaders [ FDirName $(OBOS_TOP) src servers app drawing Painter drawing_modes ] ;
|
||||
UseHeaders [ FDirName $(OBOS_TOP) src servers app drawing Painter font_support ] ;
|
||||
UseFreeTypeHeaders ;
|
||||
|
||||
Server fake_app_server :
|
||||
AppServer.cpp
|
||||
ServerApp.cpp
|
||||
BGet++.cpp
|
||||
Utils.cpp
|
||||
: libroot.so libbe.so
|
||||
;
|
1150
src/tests/apps/fake_app_server/ServerApp.cpp
Normal file
1150
src/tests/apps/fake_app_server/ServerApp.cpp
Normal file
File diff suppressed because it is too large
Load Diff
110
src/tests/apps/fake_app_server/ServerApp.h
Normal file
110
src/tests/apps/fake_app_server/ServerApp.h
Normal file
@ -0,0 +1,110 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2005, Haiku, Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: ServerApp.h
|
||||
// Author: DarkWyrm <bpmagic@columbus.rr.com>
|
||||
// Adi Oanca <adioanca@myrealbox.com>
|
||||
// Description: Server-side BApplication counterpart
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
#ifndef _SERVERAPP_H_
|
||||
#define _SERVERAPP_H_
|
||||
|
||||
#include <OS.h>
|
||||
#include <String.h>
|
||||
#include <LinkMsgReader.h>
|
||||
#include <LinkMsgSender.h>
|
||||
//#include "FMWList.h"
|
||||
|
||||
class AppServer;
|
||||
class BMessage;
|
||||
class BPortLink;
|
||||
class BList;
|
||||
class DisplayDriver;
|
||||
class ServerCursor;
|
||||
class ServerBitmap;
|
||||
class AreaPool;
|
||||
|
||||
/*!
|
||||
\class ServerApp ServerApp.h
|
||||
\brief Counterpart to BApplication within the app_server
|
||||
*/
|
||||
class ServerApp
|
||||
{
|
||||
public:
|
||||
ServerApp(port_id sendport, port_id rcvport, port_id clientLooperPort,
|
||||
team_id clientTeamID, int32 handlerID, char *signature);
|
||||
virtual ~ServerApp(void);
|
||||
|
||||
bool Run(void);
|
||||
static int32 MonitorApp(void *data);
|
||||
void Lock(void);
|
||||
void Unlock(void);
|
||||
bool IsLocked(void);
|
||||
|
||||
/*!
|
||||
\brief Determines whether the application is the active one
|
||||
\return true if active, false if not.
|
||||
*/
|
||||
bool IsActive(void) const { return fIsActive; }
|
||||
|
||||
void Activate(bool value);
|
||||
bool PingTarget(void);
|
||||
|
||||
void PostMessage(int32 code);
|
||||
|
||||
void SendMessageToClient( const BMessage* msg ) const;
|
||||
void SetAppCursor(void);
|
||||
|
||||
team_id ClientTeamID();
|
||||
|
||||
const char * Title() const { return fSignature.String(); }
|
||||
protected:
|
||||
friend class AppServer;
|
||||
friend class ServerWindow;
|
||||
|
||||
void DispatchMessage(int32 code, LinkMsgReader &link);
|
||||
|
||||
port_id fClientAppPort,
|
||||
fMessagePort,
|
||||
// TODO: find out why there is both the app port and the looper port. Do
|
||||
// we really need both?
|
||||
fClientLooperPort;
|
||||
|
||||
BString fSignature;
|
||||
thread_id fMonitorThreadID;
|
||||
|
||||
team_id fClientTeamID;
|
||||
|
||||
LinkMsgReader *fMsgReader;
|
||||
LinkMsgSender *fMsgSender;
|
||||
|
||||
/* BList *fSWindowList,
|
||||
*fBitmapList,
|
||||
*fPictureList;
|
||||
*/ sem_id fLockSem;
|
||||
bool fCursorHidden;
|
||||
bool fIsActive;
|
||||
int32 fHandlerToken;
|
||||
AreaPool *fSharedMem;
|
||||
};
|
||||
|
||||
#endif
|
327
src/tests/apps/fake_app_server/Utils.cpp
Normal file
327
src/tests/apps/fake_app_server/Utils.cpp
Normal file
@ -0,0 +1,327 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2002, Haiku
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: Utils.cpp
|
||||
// Author: DarkWyrm <bpmagic@columbus.rr.com>
|
||||
// Description: Miscellaneous utility functions
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
#include <Entry.h>
|
||||
#include <stdio.h>
|
||||
#include "Utils.h"
|
||||
#include <String.h>
|
||||
|
||||
/*!
|
||||
\brief Send a BMessage to a Looper target
|
||||
\param port Receiver port of the targeted Looper
|
||||
\param BMessage to send
|
||||
|
||||
This SendMessage takes ownership of the message sent, so deleting them after this
|
||||
call is unnecessary. Passing an invalid port will have unpredictable results.
|
||||
*/
|
||||
void SendMessage(port_id port, BMessage *message, int32 target)
|
||||
{
|
||||
if(!message)
|
||||
return;
|
||||
|
||||
if(target==-1)
|
||||
_set_message_target_(message,target,true);
|
||||
else
|
||||
_set_message_target_(message,target,false);
|
||||
|
||||
ssize_t flatsize=message->FlattenedSize();
|
||||
char *buffer=new char[flatsize];
|
||||
|
||||
if(message->Flatten(buffer,flatsize)==B_OK)
|
||||
write_port(port, message->what, buffer,flatsize);
|
||||
|
||||
delete [] buffer;
|
||||
delete message;
|
||||
}
|
||||
|
||||
/*
|
||||
Below are friend functions for BMessage which currently are not in the Message.cpp
|
||||
that we need to send messages to BLoopers and such. Placed here to allow compilation.
|
||||
*/
|
||||
void _set_message_target_(BMessage *msg, int32 target, bool preferred)
|
||||
{
|
||||
if (preferred)
|
||||
{
|
||||
msg->fTarget = -1;
|
||||
msg->fPreferred = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
msg->fTarget = target;
|
||||
msg->fPreferred = false;
|
||||
}
|
||||
}
|
||||
|
||||
int32 _get_message_target_(BMessage *msg)
|
||||
{
|
||||
if (msg->fPreferred)
|
||||
return -1;
|
||||
else
|
||||
return msg->fTarget;
|
||||
}
|
||||
|
||||
bool _use_preferred_target_(BMessage *msg)
|
||||
{
|
||||
return msg->fPreferred;
|
||||
}
|
||||
|
||||
const char *MsgCodeToString(int32 code)
|
||||
{
|
||||
// Used to translate BMessage message codes back to a character
|
||||
// format
|
||||
char string [10];
|
||||
sprintf(string,"'%x%x%x%x'",(char)((code & 0xFF000000) >> 24),
|
||||
(char)((code & 0x00FF0000) >> 16),
|
||||
(char)((code & 0x0000FF00) >> 8),
|
||||
(char)((code & 0x000000FF)) );
|
||||
return string;
|
||||
}
|
||||
|
||||
BString MsgCodeToBString(int32 code)
|
||||
{
|
||||
// Used to translate BMessage message codes back to a character
|
||||
// format
|
||||
char string [10];
|
||||
sprintf(string,"'%x%x%x%x'",(char)((code & 0xFF000000) >> 24),
|
||||
(char)((code & 0x00FF0000) >> 16),
|
||||
(char)((code & 0x0000FF00) >> 8),
|
||||
(char)((code & 0x000000FF)) );
|
||||
|
||||
BString bstring(string);
|
||||
return bstring;
|
||||
}
|
||||
|
||||
status_t ConvertModeToDisplayMode(uint32 mode, display_mode *dmode)
|
||||
{
|
||||
if(!mode)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case B_8_BIT_640x400:
|
||||
{
|
||||
dmode->virtual_width=640;
|
||||
dmode->virtual_height=400;
|
||||
dmode->space=B_CMAP8;
|
||||
break;
|
||||
}
|
||||
case B_8_BIT_640x480:
|
||||
{
|
||||
dmode->virtual_width=640;
|
||||
dmode->virtual_height=480;
|
||||
dmode->space=B_CMAP8;
|
||||
break;
|
||||
}
|
||||
case B_15_BIT_640x480:
|
||||
{
|
||||
dmode->virtual_width=640;
|
||||
dmode->virtual_height=480;
|
||||
dmode->space=B_RGB15;
|
||||
break;
|
||||
}
|
||||
case B_16_BIT_640x480:
|
||||
{
|
||||
dmode->virtual_width=640;
|
||||
dmode->virtual_height=480;
|
||||
dmode->space=B_RGB16;
|
||||
break;
|
||||
}
|
||||
case B_32_BIT_640x480:
|
||||
{
|
||||
dmode->virtual_width=640;
|
||||
dmode->virtual_height=480;
|
||||
dmode->space=B_RGB32;
|
||||
break;
|
||||
}
|
||||
case B_8_BIT_800x600:
|
||||
{
|
||||
dmode->virtual_width=800;
|
||||
dmode->virtual_height=600;
|
||||
dmode->space=B_CMAP8;
|
||||
break;
|
||||
}
|
||||
case B_15_BIT_800x600:
|
||||
{
|
||||
dmode->virtual_width=800;
|
||||
dmode->virtual_height=600;
|
||||
dmode->space=B_RGB15;
|
||||
break;
|
||||
}
|
||||
case B_16_BIT_800x600:
|
||||
{
|
||||
dmode->virtual_width=800;
|
||||
dmode->virtual_height=600;
|
||||
dmode->space=B_RGB16;
|
||||
break;
|
||||
}
|
||||
case B_32_BIT_800x600:
|
||||
{
|
||||
dmode->virtual_width=800;
|
||||
dmode->virtual_height=600;
|
||||
dmode->space=B_RGB32;
|
||||
break;
|
||||
}
|
||||
case B_8_BIT_1024x768:
|
||||
{
|
||||
dmode->virtual_width=1024;
|
||||
dmode->virtual_height=768;
|
||||
dmode->space=B_CMAP8;
|
||||
break;
|
||||
}
|
||||
case B_15_BIT_1024x768:
|
||||
{
|
||||
dmode->virtual_width=1024;
|
||||
dmode->virtual_height=768;
|
||||
dmode->space=B_RGB15;
|
||||
break;
|
||||
}
|
||||
case B_16_BIT_1024x768:
|
||||
{
|
||||
dmode->virtual_width=1024;
|
||||
dmode->virtual_height=768;
|
||||
dmode->space=B_RGB16;
|
||||
break;
|
||||
}
|
||||
case B_32_BIT_1024x768:
|
||||
{
|
||||
dmode->virtual_width=1024;
|
||||
dmode->virtual_height=768;
|
||||
dmode->space=B_RGB32;
|
||||
break;
|
||||
}
|
||||
case B_8_BIT_1152x900:
|
||||
{
|
||||
dmode->virtual_width=1152;
|
||||
dmode->virtual_height=900;
|
||||
dmode->space=B_CMAP8;
|
||||
break;
|
||||
}
|
||||
case B_15_BIT_1152x900:
|
||||
{
|
||||
dmode->virtual_width=1152;
|
||||
dmode->virtual_height=900;
|
||||
dmode->space=B_RGB15;
|
||||
break;
|
||||
}
|
||||
case B_16_BIT_1152x900:
|
||||
{
|
||||
dmode->virtual_width=1152;
|
||||
dmode->virtual_height=900;
|
||||
dmode->space=B_RGB16;
|
||||
break;
|
||||
}
|
||||
case B_32_BIT_1152x900:
|
||||
{
|
||||
dmode->virtual_width=1152;
|
||||
dmode->virtual_height=900;
|
||||
dmode->space=B_RGB32;
|
||||
break;
|
||||
}
|
||||
case B_8_BIT_1280x1024:
|
||||
{
|
||||
dmode->virtual_width=1280;
|
||||
dmode->virtual_height=1024;
|
||||
dmode->space=B_CMAP8;
|
||||
break;
|
||||
}
|
||||
case B_15_BIT_1280x1024:
|
||||
{
|
||||
dmode->virtual_width=1280;
|
||||
dmode->virtual_height=1024;
|
||||
dmode->space=B_RGB15;
|
||||
break;
|
||||
}
|
||||
case B_16_BIT_1280x1024:
|
||||
{
|
||||
dmode->virtual_width=1280;
|
||||
dmode->virtual_height=1024;
|
||||
dmode->space=B_RGB16;
|
||||
break;
|
||||
}
|
||||
case B_32_BIT_1280x1024:
|
||||
{
|
||||
dmode->virtual_width=1280;
|
||||
dmode->virtual_height=1024;
|
||||
dmode->space=B_RGB32;
|
||||
break;
|
||||
}
|
||||
case B_8_BIT_1600x1200:
|
||||
{
|
||||
dmode->virtual_width=1600;
|
||||
dmode->virtual_height=1200;
|
||||
dmode->space=B_CMAP8;
|
||||
break;
|
||||
}
|
||||
case B_15_BIT_1600x1200:
|
||||
{
|
||||
dmode->virtual_width=1600;
|
||||
dmode->virtual_height=1200;
|
||||
dmode->space=B_RGB15;
|
||||
break;
|
||||
}
|
||||
case B_16_BIT_1600x1200:
|
||||
{
|
||||
dmode->virtual_width=1600;
|
||||
dmode->virtual_height=1200;
|
||||
dmode->space=B_RGB16;
|
||||
break;
|
||||
}
|
||||
case B_32_BIT_1600x1200:
|
||||
{
|
||||
dmode->virtual_width=1600;
|
||||
dmode->virtual_height=1200;
|
||||
dmode->space=B_RGB32;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return B_ERROR;
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
BRect CalculatePolygonBounds(BPoint *pts, int32 pointcount)
|
||||
{
|
||||
if(!pts)
|
||||
return BRect(0,0,0,0);
|
||||
|
||||
BRect r(0,0,0,0);
|
||||
|
||||
// shamelessly stolen from Marc's BPolygon code and tweaked to fit. :P
|
||||
r = BRect(pts[0], pts[0]);
|
||||
|
||||
for (int32 i = 1; i < 4; i++)
|
||||
{
|
||||
if (pts[i].x < r.left)
|
||||
r.left = pts[i].x;
|
||||
if (pts[i].y < r.top)
|
||||
r.top = pts[i].y;
|
||||
if (pts[i].x > r.right)
|
||||
r.right = pts[i].x;
|
||||
if (pts[i].y > r.bottom)
|
||||
r.bottom = pts[i].y;
|
||||
}
|
||||
return r;
|
||||
}
|
39
src/tests/apps/fake_app_server/Utils.h
Normal file
39
src/tests/apps/fake_app_server/Utils.h
Normal file
@ -0,0 +1,39 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2002, Haiku
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: Utils.h
|
||||
// Author: DarkWyrm <bpmagic@columbus.rr.com>
|
||||
// Description: Miscellaneous utility functions
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
#ifndef UTILS_H_
|
||||
#define UTILS_H_
|
||||
|
||||
#include <Message.h>
|
||||
#include <OS.h>
|
||||
#include <Accelerant.h>
|
||||
|
||||
void SendMessage(port_id port, BMessage *message, int32 target=-1);
|
||||
const char *MsgCodeToString(int32 code);
|
||||
BString MsgCodeToBString(int32 code);
|
||||
status_t ConvertModeToDisplayMode(uint32 mode, display_mode *dmode);
|
||||
BRect CalculatePolygonBounds(BPoint *pts, int32 pointcount);
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user