From 35128bfc234c3fa1e1c62f2a3279641df618d6b6 Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Wed, 10 Aug 2022 02:47:39 -0400 Subject: [PATCH] use new aligned atomic types everywhere See 69448b13a10a14517 / #1969; the compiler can now ensure that a uint64 intended for atomic access is always aligned to a 64-bit boundary. Convert atomic operations on uint32s and pointers as well. --- irc/client.go | 4 ++-- irc/getters.go | 5 ++--- irc/logger/logger.go | 8 ++++---- irc/mysql/history.go | 18 +++++++++--------- irc/server.go | 4 ++-- irc/usermaskset.go | 13 ++++++------- 6 files changed, 25 insertions(+), 27 deletions(-) diff --git a/irc/client.go b/irc/client.go index debc8b1e..a9cf5b05 100644 --- a/irc/client.go +++ b/irc/client.go @@ -165,7 +165,7 @@ type Session struct { sasl saslStatus passStatus serverPassStatus - batchCounter uint32 + batchCounter atomic.Uint32 quitMessage string @@ -262,7 +262,7 @@ func (session *Session) HasHistoryCaps() bool { // or nesting) on an individual session connection need to be unique. // this allows ~4 billion such batches which should be fine. func (session *Session) generateBatchID() string { - id := atomic.AddUint32(&session.batchCounter, 1) + id := session.batchCounter.Add(1) return strconv.FormatInt(int64(id), 32) } diff --git a/irc/getters.go b/irc/getters.go index 6e5718b6..78a39429 100644 --- a/irc/getters.go +++ b/irc/getters.go @@ -6,7 +6,6 @@ package irc import ( "fmt" "net" - "sync/atomic" "time" "github.com/ergochat/ergo/irc/caps" @@ -36,11 +35,11 @@ func (server *Server) Languages() (lm *languages.Manager) { } func (server *Server) Defcon() uint32 { - return atomic.LoadUint32(&server.defcon) + return server.defcon.Load() } func (server *Server) SetDefcon(defcon uint32) { - atomic.StoreUint32(&server.defcon, defcon) + server.defcon.Store(defcon) } func (client *Client) Sessions() (sessions []*Session) { diff --git a/irc/logger/logger.go b/irc/logger/logger.go index a07109a2..c8a8987b 100644 --- a/irc/logger/logger.go +++ b/irc/logger/logger.go @@ -69,7 +69,7 @@ type Manager struct { loggers []singleLogger stdoutWriteLock sync.Mutex // use one lock for both stdout and stderr fileWriteLock sync.Mutex - loggingRawIO uint32 + loggingRawIO atomic.Uint32 } // LoggingConfig represents the configuration of a single logger. @@ -107,7 +107,7 @@ func (logger *Manager) ApplyConfig(config []LoggingConfig) error { } logger.loggers = nil - atomic.StoreUint32(&logger.loggingRawIO, 0) + logger.loggingRawIO.Store(0) // for safety, this deep-copies all mutable data in `config` // XXX let's keep it that way @@ -138,7 +138,7 @@ func (logger *Manager) ApplyConfig(config []LoggingConfig) error { ioEnabled := typeMap["userinput"] || typeMap["useroutput"] || (typeMap["*"] && !(excludedTypeMap["userinput"] && excludedTypeMap["useroutput"])) // raw I/O is only logged at level debug; if ioEnabled && logConfig.Level == LogDebug { - atomic.StoreUint32(&logger.loggingRawIO, 1) + logger.loggingRawIO.Store(1) } if sLogger.MethodFile.Enabled { file, err := os.OpenFile(sLogger.MethodFile.Filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666) @@ -157,7 +157,7 @@ func (logger *Manager) ApplyConfig(config []LoggingConfig) error { // IsLoggingRawIO returns true if raw user input and output is being logged. func (logger *Manager) IsLoggingRawIO() bool { - return atomic.LoadUint32(&logger.loggingRawIO) == 1 + return logger.loggingRawIO.Load() == 1 } // Log logs the given message with the given details. diff --git a/irc/mysql/history.go b/irc/mysql/history.go index 9ccb109d..4cb985f4 100644 --- a/irc/mysql/history.go +++ b/irc/mysql/history.go @@ -45,10 +45,8 @@ const ( type e struct{} type MySQL struct { - timeout *int64 - trackAccountMessages uint32 - db *sql.DB - logger *logger.Manager + db *sql.DB + logger *logger.Manager insertHistory *sql.Stmt insertSequence *sql.Stmt @@ -60,22 +58,24 @@ type MySQL struct { config Config wakeForgetter chan e + + timeout atomic.Uint64 + trackAccountMessages atomic.Uint32 } func (mysql *MySQL) Initialize(logger *logger.Manager, config Config) { - mysql.timeout = new(int64) mysql.logger = logger mysql.wakeForgetter = make(chan e, 1) mysql.SetConfig(config) } func (mysql *MySQL) SetConfig(config Config) { - atomic.StoreInt64(mysql.timeout, int64(config.Timeout)) + mysql.timeout.Store(uint64(config.Timeout)) var trackAccountMessages uint32 if config.TrackAccountMessages { trackAccountMessages = 1 } - atomic.StoreUint32(&mysql.trackAccountMessages, trackAccountMessages) + mysql.trackAccountMessages.Store(trackAccountMessages) mysql.stateMutex.Lock() mysql.config = config mysql.stateMutex.Unlock() @@ -555,11 +555,11 @@ func (mysql *MySQL) prepareStatements() (err error) { } func (mysql *MySQL) getTimeout() time.Duration { - return time.Duration(atomic.LoadInt64(mysql.timeout)) + return time.Duration(mysql.timeout.Load()) } func (mysql *MySQL) isTrackingAccountMessages() bool { - return atomic.LoadUint32(&mysql.trackAccountMessages) != 0 + return mysql.trackAccountMessages.Load() != 0 } func (mysql *MySQL) logError(context string, err error) (quit bool) { diff --git a/irc/server.go b/irc/server.go index 95c20eda..058c7372 100644 --- a/irc/server.go +++ b/irc/server.go @@ -91,7 +91,7 @@ type Server struct { stats Stats semaphores ServerSemaphores flock flock.Flocker - defcon uint32 + defcon atomic.Uint32 } // NewServer returns a new Oragono server. @@ -103,8 +103,8 @@ func NewServer(config *Config, logger *logger.Manager) (*Server, error) { logger: logger, rehashSignal: make(chan os.Signal, 1), exitSignals: make(chan os.Signal, len(utils.ServerExitSignals)), - defcon: 5, } + server.defcon.Store(5) server.accepts.Initialize() server.clients.Initialize() diff --git a/irc/usermaskset.go b/irc/usermaskset.go index 81569709..b4e551f3 100644 --- a/irc/usermaskset.go +++ b/irc/usermaskset.go @@ -11,7 +11,6 @@ import ( "sync" "sync/atomic" "time" - "unsafe" "github.com/ergochat/ergo/irc/utils" ) @@ -27,8 +26,8 @@ type UserMaskSet struct { sync.RWMutex serialCacheUpdateMutex sync.Mutex masks map[string]MaskInfo - regexp unsafe.Pointer - muteRegexp unsafe.Pointer + regexp atomic.Pointer[regexp.Regexp] + muteRegexp atomic.Pointer[regexp.Regexp] } func NewUserMaskSet() *UserMaskSet { @@ -110,7 +109,7 @@ func (set *UserMaskSet) Masks() (result map[string]MaskInfo) { // Match matches the given n!u@h against the standard (non-ext) bans. func (set *UserMaskSet) Match(userhost string) bool { - regexp := (*regexp.Regexp)(atomic.LoadPointer(&set.regexp)) + regexp := set.regexp.Load() if regexp == nil { return false @@ -129,7 +128,7 @@ func (set *UserMaskSet) MatchMute(userhost string) bool { } func (set *UserMaskSet) MuteRegexp() *regexp.Regexp { - return (*regexp.Regexp)(atomic.LoadPointer(&set.muteRegexp)) + return set.muteRegexp.Load() } func (set *UserMaskSet) Length() int { @@ -162,6 +161,6 @@ func (set *UserMaskSet) setRegexp() { re := compileMasks(maskExprs) muteRe := compileMasks(muteExprs) - atomic.StorePointer(&set.regexp, unsafe.Pointer(re)) - atomic.StorePointer(&set.muteRegexp, unsafe.Pointer(muteRe)) + set.regexp.Store(re) + set.muteRegexp.Store(muteRe) }