Checking !(fp->foo_flags & FOO_BUFFERED) means: this struct foo is not buffered. This is why I change it to: - if (!(fp->foo_flags & FOO_BUFFERED) && fp->foo_buffer == NULL) { + if ((fp->foo_flags & FOO_BUFFERED) && fp->foo_buffer == NULL) { As this makes me feel we ask: "If it's buffered, and the buffer is not allocated". Later, you do: - if ((fp->foo_flags & FOO_BUFFERED) || fp->foo_buffer != NULL) If we get back with FOO_BUFFERED still set, free() will be executed no matter if the foo_buffer is NULL or not. This is why I think we might want to have something obvious: + if ((fp->foo_flags & FOO_BUFFERED) && fp->foo_buffer == NULL) + fp->foo_buffer = tmpbuff; + else If we got back to the thread with a foo_flags with FOO_BUFFERED and foo_buffer is still NULL, use allocated region of memory. Otherwise (foo_flags doesn't have FOO_BUFFERED and foo_buffer isn't NULL or both), we simply free allocated memory. ==== //depot/user/attilio/attilio_smpng/locking.9#4 - /home/wkoszek/p4/locking.9/locking.9 ==== @@ -226,14 +226,14 @@ char *tmpbuff; mtx_lock(&fp->foo_mtx); - if (!(fp->foo_flags & FOO_BUFFERED) && fp->foo_buffer == NULL) { + if ((fp->foo_flags & FOO_BUFFERED) && fp->foo_buffer == NULL) { mtx_unlock(&fp->foo_mtx); tmpbuff = malloc(BUFSIZ, M_TEMP, M_ZERO | M_WAITOK); mtx_lock(&fp->foo_mtx); - if ((fp->foo_flags & FOO_BUFFERED) || fp->foo_buffer != NULL) + if ((fp->foo_flags & FOO_BUFFERED) && fp->foo_buffer == NULL) + fp->foo_buffer = tmpbuff; + else free(tmpbuff, M_TEMP); - else - fp->foo_buffer = tmpbuff; } mtx_unlock(&fp->foo_mtx); }