code: func (ctx *Ctx) Run(errChan chan error) error {
  	runtime.LockOSThread()
  
  	// set current, which locks the context to the OS thread
  	if err := SetCurrentContext(ctx.CUContext); err != nil {
  		if errChan != nil {
  			errChan <- err
  		} else {
  			return err
  		}
  		return nil
  	}
  	close(errChan)
  
  	// wait for Do()s
  	for w := range ctx.work {
  		ctx.errChan <- w()
  	}
  	runtime.UnlockOSThread()
  	return nil
  }
docs: // Run locks the goroutine to the OS thread and ties the CUDA context to the OS thread. For most cases, this would suffice
  //
  // Note: errChan that is passed in should NOT be the same errChan as the one used internally for signalling.
  // The main reasoning for passing in an error channel is to support two different kinds of run modes:
  //
  // The typical use example is as such:
  //
  /*
  	func A() {
  			ctx := NewContext(d, SchedAuto)
  			errChan := make(chan error)
  			go ctx.Run(errChan)
  			if err := <- errChan; err != nil {
  				// handleError
  			}
  			doSomethingWithCtx(ctx)
  	}
  */
  // And yet another run mode supported is running of the context in the main thread:
  //
  /*
  	func main() {
  		ctx := NewContext(d, SchedAuto)
  		go doSomethingWithCtx(ctx)
  		if err := ctx.Run(nil); err != nil{
  			// handle error
  		}
  	}
  */