Updates & Twitter

Keep me going
give me coffee! Smoke 1 Smoke 2 Smoke 3

Just a small hint on what I do, and why there are not to much updates to this blog...

I usually post, if I have something to offer, except on my "small sources of joy" – and by offering I don't think on "offering apologies on why there are no updates today" 🙂 . I use most of my time to propel my projects, writing the blog-entry is to dot the i.

I hear you, I read all your comments (as I have to allow them to the board), I read all the emails – but I can only answer that much. I really hear you.

But if you want to
- feel the pulse
- know where I run into building problems with latest darwine
- what features rpncalc is receiving this instant
- see if i find a fix to the prefix problem in ies4osx

...have a look at twitter or even follow me – as I often drop a line when I hit my head.

http://twitter.com/k3erg

Q-0.9.1d104

Here is the first nightly of the last line of builds for Q1. After, we move to Q2.

Main changes:

Grab the new Q nightly at http://www.kju-app.org.

shared memory on Mac OS X

As I'm currently rewriting Q - [kju:] from scratch, I have to tackle a longstanding QEMU frontend problem: vga buffer of the guest os in one application - vga output window in a viewing/controlling app.
The most economic would be a buffer that could be accessed by both apps. Shared Memory.
There was once a shmem patch submitted to the QEMU dev list, but it got dropped in favor for a vnc solution. As I'm not satisfied with vnc speed, I took a stab at the shmem patch.

shmem on OS X, it's a no-go...
Shmem would be the most geleagnt way of creating shared memory. Unfortunateley, Apple has limited shmem to a lousy 4MB - for the whole system!Blade:~ mike$ cat /etc/rc | grep shmmax
sysctl -w kern.sysv.shmmax=4194304 kern.sysv.shmmin=1 kern.sysv.shmmni=32 kern.sysv.shmseg=8 kern.sysv.shmall=1024
Manipulating rc is not my thing. Setting shmem with 'sysctl -w kern.sysv.shmmax=10485760' to 10MB on the fly needs to much privileges.

Distributed Object, anybody?
I'm already using DO to communicate between the controoling ap and the QEMU instances. The problem with DO is, that all the messages are copied and sent to the corresponding object. So accessing a buffer in a distandt object with - (void *) screenBuffer; will copy and send the whole buffer, not just a memorypointer. The advantage of the DO, you could have the viewer on a different machine - (Q - [kju:] Server anybody? :)).
So I wrote a methode, that just sends updated segments of the screenBuffer.
Here is a downstripped version of the Distributed Object (DO) I used to transfer changes in the guests videoram to the viewer:

DO in data reciever process:

@protocol RecieverObjectProto
- (void) updateBufferWithData:(NSData*)data
            start:(size_t)start
            length:(size_t)length;
@end
 
@interface RecieverObject : NSObject <RecieverObjectProto> {
    void *destinationbuffer;
}
- (void) updateBufferWithData:(NSData*)data
            start:(size_t)start
            length:(size_t)length;
@end
 
@implementation RecieverObject
- (id) initWithSender:(id)sender
{
    self = [super init];
    if (self) {
 
        // our buffer
        destinationbuffer = malloc(1024*1024*10);
 
        // Open a connection, so the client can connect to us
        NSConnection *connection = [NSConnection defaultConnection];
        [connection setRootObject:self];
        if ([connection registerName:@"buffer"] == NO) {
            NSLog(@"Could not establisch buffer server");
            return nil;
        }
    }
    return self;
}
 
- (void) dealloc
{
    if (destinationbuffer)
        free(destinationbuffer);
    [super dealloc];
}
 
- (void) updateBufferWithData:(NSData*)data
            start:(size_t)start
            length:(size_t)length
{
    UInt8 *pixelPointer;
    pixelPointer = destinationbuffer;
    memcpy(&pixelPointer[start], [data bytes], length);
}
@end

DO in data creator process:

@interface SenderObject : NSObject {
    RecieverObject* qDocument
    void *sourcebuffer;
}
- (void) sendBufferUpdate;
@end
 
@implementation SenderObject
- (id) init
{
    self = [super init];
    if (self) {
        // connect to the QDocument object
        qDocument = [[NSConnection
            rootProxyForConnectionWithRegisteredName:@"buffer"
            host:nil] retain];
        if(!qDocument) {
            NSLog(@"Could not connect to buffer");
            return FALSE;
        }
 
        sourcebuffer = malloc(1024*1024*10);
 
        return self;
    }
    return nil;
}
 
- (void) dealloc
{
    if (sourcebuffer)
        free(sourcebuffer);
    [super dealloc];
}
 
- (void) sendBufferUpdate
{
    size_t start = 1024; // start to send data from offset 'start'
    size_t length = 1024; // send 'length' bytes
    UInt8 *pixelPointer;
    pixelPointer = sourcebuffer;
 
     // note: I use dataWithBytesNoCopy => one time less copying
    data = [NSData dataWithBytesNoCopy:&pixelPointer[start]
                length:length freeWhenDone:NO];
 
    // lets send the data
    [qDocument updateBufferWithData:data start:start length:length];
}
@end

Downside of the shared Object: data is copied at least 2 times: when the message is created and when the data is writen from the message to the reciveers buffer. Faster than vnc... but data objects are sometimes not released as fast as created => incredible memory footprint.

finally, mmap!
With mmap you can load a file into memory. If more than one processes mmap the same file, all processes can access the same mmap, that way we have shared memory, and a convenient way to share the adress: the file.

First we need a file the size we need shared memory...

// we need a dummy file, this gives us the possibility to
// access the shared memory over the filesystem
int bufferSize;
int fd, ret;
bufferSize = 1024*1024*10;
void *dummyFile;
dummyFile = malloc(bufferSize);
 
// open trunkate/create read/write for everybody
fd = open("/tmp/myRamFile", O_CREAT|O_RDWR, 0666);
if (fd == -1) {
    NSLog(@"Could not open '/tmp/myRamFile'");
}
ret = write(fd, dummyFile, bufferSize); // create the file
ret = close(fd);
free(dummyFile);

...after we attach, from multiple processes.

// open the file with read & write access
fd = open("/tmp/myRamFile", O_RDWR);
if(!fd)
    NSLog(@"Could not open '/tmp/myRamFile'");
 
// load the file into memory, shared, read & write access
int buffersize = 1024*1024*10;
void *sourcebuffer = mmap(
    0, buffersize, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, fd, 0);
if(!sourcebuffer)
    NSLog(@"Could not mmap '/tmp/%s.vga'");
 
// once the file is mapped, we can dispose of the filehandle
close(fd);
 
//... do something intresting with the shared memory, then unmap
if (sourcebuffer)
    munmap(sourcebuffer, buffersize);

Downside? Well if more than one process make changes to the mmaped file, it's writen from time to time (normally when the last process exits) but I can live with that.
I hope to comit the rewrite of Q - [kju:] soon 🙂

Mike

Q-0.9.0

elive gem on Q - [kju:]After about a year we have finally a new stable of Q.
It's based on the Qemu 0.9.0 release, with some packported bugfixes from Qemu CVS.
Cordney* has added many new features, andi sponsored a new set of icons, while I fiddled with output and guest switching.

Basically I made the Quartz output default. Quartz is no longer refreshing or drawing items that did not change. This speeds up emulation quite a bit, especially on more static programs. Fullscreen programs like games with a lot of action still perform better with the OpenGL output.
Fullscreen guest switching makes use of the obligate cube animation :).

BTW: the guest is elive gem (night theme).

Hope You enjoy it.

Take me to Q!

Q-0.9.0d86

Well building is building - so I built this new nightly of Q during a break while building a new wall in our garden ;).

Grab the new Q nightly at http://www.kju-app.org.