uuid icon indicating copy to clipboard operation
uuid copied to clipboard

Is it thread safe to read\write a global integer variable during v7 UUID creation ?

Open illia-imperva opened this issue 1 year ago • 2 comments

Is it thread safe to read\write the global integer variable lastV7time during v7 UUID creation ?

illia-imperva avatar Oct 14 '24 05:10 illia-imperva

The lastV7time

// lastV7time is the last time we returned stored as:
//
//	52 bits of time in milliseconds since epoch
//	12 bits of (fractional nanoseconds) >> 8
var lastV7time int64

const nanoPerMilli = 1000000

// getV7Time returns the time in milliseconds and nanoseconds / 256.
// The returned (milli << 12 + seq) is guaranteed to be greater than
// (milli << 12 + seq) returned by any previous call to getV7Time.
func getV7Time() (milli, seq int64) {
	timeMu.Lock()
	defer timeMu.Unlock()

	nano := timeNow().UnixNano()
	milli = nano / nanoPerMilli
	// Sequence number is between 0 and 3906 (nanoPerMilli>>8)
	seq = (nano - milli*nanoPerMilli) >> 8
	now := milli<<12 + seq
	if now <= lastV7time {
		now = lastV7time + 1
		milli = now >> 12
		seq = now & 0xfff
	}
	lastV7time = now
	return milli, seq
}

illia-imperva avatar Oct 14 '24 05:10 illia-imperva

I think it has to be changed to atomic int64 at least...

ilqvya avatar Oct 14 '24 07:10 ilqvya

it has mutex, it's safe, there is no multiple-goroutine read and write on lastV7time

https://github.com/google/uuid/blob/0e97ed3b537927cb4afea366bc4cc36f6eb37e75/version7.go#L88-L90

trim21 avatar Oct 26 '24 08:10 trim21

That's good, but it does not solve what the global variable and mutex are supposed to solve. Due to any modern Operational System preemptive scheduling the function might run into case when 1st thread exits mutex before returning value to client code while 2nd thread executes the function and returns next value to client code, after that 1st thread continues and returns value with timestamp lower than already returned value

illia-imperva avatar Oct 28 '24 06:10 illia-imperva

That's good, but it does not solve what the global variable and mutex are supposed to solve. Due to any modern Operational System preemptive scheduling the function might run into case when 1st thread exits mutex before returning value to client code while 2nd thread executes the function and returns next value to client code, after that 1st thread continues and returns value with timestamp lower than already returned value

that would be a bug of go compiler, right?

trim21 avatar Oct 28 '24 06:10 trim21