[haiku-development] Re: Increase syslog_buffer_size

  • From: Colin Günther <coling@xxxxxx>
  • To: haiku-development@xxxxxxxxxxxxx
  • Date: Thu, 18 Mar 2010 00:56:36 +0100

On 06.03.2010 17:10, Ingo Weinhold wrote:

Come to think of it, the space problem occurs only during the boot process,
before the syslog daemon is running. I guess we should simply allocate a
more generous buffer for the boot process and shrink it back once the
buffer has been emptied.

CU, Ingo


Ok, I looked into how to figure out when the buffer is empty to shrink the syslog buffer again this is what I came up with something like this:

modifying syslog_sender in debug.cpp (note this is only a sketch to show what I'm up to):

while (true){
<snip>
if (port >= B_OK) {
            if (!bufferPending) {
                // we need to have exclusive access to our syslog buffer
                cpu_status state = disable_interrupts();
                acquire_spinlock(&sSpinlock);

                length = ring_buffer_readable(sSyslogBuffer);
                if (length > (int32)SYSLOG_MAX_MESSAGE_LENGTH)
                    length = SYSLOG_MAX_MESSAGE_LENGTH;

                length = ring_buffer_read(sSyslogBuffer,
                    (uint8*)sSyslogMessage->message, length);
                if (sSyslogDropped) {
// Add drop marker - since parts had to be dropped, it's // guaranteed that we have enough space in the buffer now.
                    ring_buffer_write(sSyslogBuffer, (uint8*)"<DROP>", 6);
                    sSyslogDropped = false;
                }

+                if (sSyslogBuffer->resizeCount == 0)
+                       downsize_ring_buffer_if_empty(sSyslogBuffer);

                release_spinlock(&sSpinlock);
                restore_interrupts(state);
            }
<snip>
}

modifiying ring_buffer:

struct ring_buffer {
    int32        first;
    int32        in;
    int32        size;
+  int32        resizeCount; // Counts how often the buffer was resized
    uint8        buffer[0];
};


+/* Downsizes the passed parameter only when
+         1. The new size is smaller then the current size
+         2. Memory for the downsized buffer can be allocated.
+         3. The buffer is currently empty.
+    If downsizing fails the original buffer will be untouched.
+ */
+void
+downsize_ring_buffer_if_empty(struct ring_buffer* currentBuffer,
+        size_t newSize = DEFAULT_SYSLOG_BUFFER_SIZE)
+{
+    if (currentBuffer->size > newSize && currentBuffer->size == 0) {
+        struct ring_buffer* newBuffer = create_ring_buffer(newSize);
+        if (newBuffer == NULL)
+            return;
+
+        newBuffer->resizeCount = currentBuffer->resizeCount
+        delete_ring_buffer(currentBuffer);
+        newBuffer->resizeCount++;
+        currentBuffer = newBuffer;
+    }
+}

My main concerns about this implementation is regarding the syslog_sender where the check for downsizing happens all the time. Would this be neglectable or is there another solution I'm just missing?

And as it turned out, the maximum syslog_buffer_size is hardcoded to 262144 Bytes (which i wasn't aware of), though my original proposal of roughly 1 MB would scale down to this maximum value, in the end. So maybe the dynamic downsizing is needed anyway.,

Kind Regards
-Colin

Other related posts: