responding to review feedback
diff --git a/gocheck.go b/gocheck.go
index e6ab66c..8c727a3 100644
--- a/gocheck.go
+++ b/gocheck.go
@@ -54,15 +54,16 @@
 }
 
 type C struct {
-	method   *methodType
-	kind     funcKind
-	status   funcStatus
-	logb     logger
-	logw     io.Writer
-	done     chan *C
-	reason   string
-	mustFail bool
-	tempDir  *tempDir
+	method    *methodType
+	kind      funcKind
+	status    funcStatus
+	writeLock sync.Mutex // protects logb from concurrent writes
+	logb      *bytes.Buffer
+	logw      io.Writer
+	done      chan *C
+	reason    string
+	mustFail  bool
+	tempDir   *tempDir
 	timer
 }
 
@@ -121,12 +122,6 @@
 	return path
 }
 
-type logger interface {
-	io.Writer
-	io.WriterTo
-	fmt.Stringer
-}
-
 // -----------------------------------------------------------------------
 // Low-level logging functions.
 
@@ -143,10 +138,12 @@
 }
 
 func (c *C) writeLog(buf []byte) {
+	c.writeLock.Lock()
 	c.logb.Write(buf)
 	if c.logw != nil {
 		c.logw.Write(buf)
 	}
+	c.writeLock.Unlock()
 }
 
 func hasStringOrError(x interface{}) (ok bool) {
@@ -590,13 +587,13 @@
 
 // Create a call object with the given suite method, and fork a
 // goroutine with the provided dispatcher for running it.
-func (runner *suiteRunner) forkCall(method *methodType, kind funcKind, logb logger, dispatcher func(c *C)) *C {
+func (runner *suiteRunner) forkCall(method *methodType, kind funcKind, logb *bytes.Buffer, dispatcher func(c *C)) *C {
 	var logw io.Writer
 	if runner.output.Stream {
 		logw = runner.output
 	}
 	if logb == nil {
-		logb = &serialisedLogger{}
+		logb = bytes.NewBuffer(nil)
 	}
 	c := &C{
 		method:  method,
@@ -616,32 +613,8 @@
 	return c
 }
 
-// serialisedLogger serialises calls to the underlying buffer.
-type serialisedLogger struct {
-	sync.Mutex
-	b bytes.Buffer
-}
-
-func (l *serialisedLogger) Write(buf []byte) (int, error) {
-	l.Lock()
-	defer l.Unlock()
-	return l.b.Write(buf)
-}
-
-func (l *serialisedLogger) WriteTo(w io.Writer) (int64, error) {
-	l.Lock()
-	defer l.Unlock()
-	return l.b.WriteTo(w)
-}
-
-func (l *serialisedLogger) String() string {
-	l.Lock()
-	defer l.Unlock()
-	return l.b.String()
-}
-
 // Same as forkCall(), but wait for call to finish before returning.
-func (runner *suiteRunner) runFunc(method *methodType, kind funcKind, logb logger, dispatcher func(c *C)) *C {
+func (runner *suiteRunner) runFunc(method *methodType, kind funcKind, logb *bytes.Buffer, dispatcher func(c *C)) *C {
 	c := runner.forkCall(method, kind, logb, dispatcher)
 	<-c.done
 	return c
@@ -684,7 +657,7 @@
 // goroutine like all suite methods, but this method will not return
 // while the fixture goroutine is not done, because the fixture must be
 // run in a desired order.
-func (runner *suiteRunner) runFixture(method *methodType, logb logger) *C {
+func (runner *suiteRunner) runFixture(method *methodType, logb *bytes.Buffer) *C {
 	if method != nil {
 		c := runner.runFunc(method, fixtureKd, logb, func(c *C) {
 			c.ResetTimer()
@@ -700,7 +673,7 @@
 // Run the fixture method with runFixture(), but panic with a fixturePanic{}
 // in case the fixture method panics.  This makes it easier to track the
 // fixture panic together with other call panics within forkTest().
-func (runner *suiteRunner) runFixtureWithPanic(method *methodType, logb logger, skipped *bool) *C {
+func (runner *suiteRunner) runFixtureWithPanic(method *methodType, logb *bytes.Buffer, skipped *bool) *C {
 	if *skipped {
 		return nil
 	}