|  | // Copyright 2017 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package runtime | 
|  |  | 
|  | import "unsafe" | 
|  |  | 
|  | var labelSync uintptr | 
|  |  | 
|  | //go:linkname runtime_setProfLabel runtime_1pprof.runtime__setProfLabel | 
|  | func runtime_setProfLabel(labels unsafe.Pointer) { | 
|  | // Introduce race edge for read-back via profile. | 
|  | // This would more properly use &getg().labels as the sync address, | 
|  | // but we do the read in a signal handler and can't call the race runtime then. | 
|  | // | 
|  | // This uses racereleasemerge rather than just racerelease so | 
|  | // the acquire in profBuf.read synchronizes with *all* prior | 
|  | // setProfLabel operations, not just the most recent one. This | 
|  | // is important because profBuf.read will observe different | 
|  | // labels set by different setProfLabel operations on | 
|  | // different goroutines, so it needs to synchronize with all | 
|  | // of them (this wouldn't be an issue if we could synchronize | 
|  | // on &getg().labels since we would synchronize with each | 
|  | // most-recent labels write separately.) | 
|  | // | 
|  | // racereleasemerge is like a full read-modify-write on | 
|  | // labelSync, rather than just a store-release, so it carries | 
|  | // a dependency on the previous racereleasemerge, which | 
|  | // ultimately carries forward to the acquire in profBuf.read. | 
|  | if raceenabled { | 
|  | racereleasemerge(unsafe.Pointer(&labelSync)) | 
|  | } | 
|  | getg().labels = labels | 
|  | } | 
|  |  | 
|  | //go:linkname runtime_getProfLabel runtime_1pprof.runtime__getProfLabel | 
|  | func runtime_getProfLabel() unsafe.Pointer { | 
|  | return getg().labels | 
|  | } |